diff --git a/pom.xml b/pom.xml index cdb6427d33..249fed1eee 100644 --- a/pom.xml +++ b/pom.xml @@ -48,8 +48,8 @@ -SNAPSHOT UTF-8 - 9.4.41.v20210516 - 2.29.1 + 12.0.3 + 3.1.5 2.5.0 2.5.0 3.7.4 diff --git a/ugs-pendant/pom.xml b/ugs-pendant/pom.xml index afdd52e000..a24b0ecd58 100644 --- a/ugs-pendant/pom.xml +++ b/ugs-pendant/pom.xml @@ -27,22 +27,24 @@ ${commons-lang3.version} + - org.eclipse.jetty - jetty-server - ${jetty.version} + jakarta.servlet + jakarta.servlet-api + 6.0.0 - org.eclipse.jetty - jetty-servlet - ${jetty.version} + jakarta.ws.rs + jakarta.ws.rs-api + 3.1.0 - org.eclipse.jetty - jetty-util - ${jetty.version} + jakarta.websocket + jakarta.websocket-api + 2.0.0 + org.glassfish.jersey.core jersey-server @@ -73,6 +75,23 @@ jersey-media-multipart ${jersey.version} + + org.glassfish.jersey.core + jersey-client + ${jersey.version} + + + + + org.eclipse.jetty.ee10.websocket + jetty-ee10-websocket-jakarta-server + ${jetty.version} + + + org.eclipse.jetty.ee10 + jetty-ee10-servlet + ${jetty.version} + diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendAPIFactory.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendProvider.java similarity index 62% rename from ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendAPIFactory.java rename to ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendProvider.java index 76d2c31fbc..bda3c63127 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendAPIFactory.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendProvider.java @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Will Winder + Copyright 2016-2023 Will Winder This file is part of Universal Gcode Sender (UGS). @@ -21,24 +21,16 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.model.BackendAPI; /** - * A factory for accessing the backend in injected resources + * A provider for accessing the backend in injected resources */ -public class BackendAPIFactory { - private static BackendAPIFactory instance; - private BackendAPI backendAPI; - - public static BackendAPIFactory getInstance() { - if (instance == null) { - instance = new BackendAPIFactory(); - } - return instance; - } +public class BackendProvider { + private static BackendAPI backendAPI; - public void register(BackendAPI backendAPI) { - this.backendAPI = backendAPI; + public static void register(BackendAPI backendAPI) { + BackendProvider.backendAPI = backendAPI; } - public BackendAPI getBackendAPI() { + public static BackendAPI getBackendAPI() { return backendAPI; } } diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/ExceptionMapper.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/ExceptionMapper.java index 6fbd1d4784..c5eb4ed044 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/ExceptionMapper.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/ExceptionMapper.java @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Will Winder + Copyright 2016-2023 Will Winder This file is part of Universal Gcode Sender (UGS). @@ -20,11 +20,11 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.pendantui.v1.model.PendantError; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; -public class ExceptionMapper implements javax.ws.rs.ext.ExceptionMapper { +public class ExceptionMapper implements jakarta.ws.rs.ext.ExceptionMapper { @Override public Response toResponse(Exception e) { diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/PendantUI.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/PendantUI.java index 66bbd8963d..ebb6f12680 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/PendantUI.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/PendantUI.java @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Will Winder + Copyright 2016-2023 Will Winder This file is part of Universal Gcode Sender (UGS). @@ -22,24 +22,27 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.model.BackendAPI; import com.willwinder.universalgcodesender.model.UGSEvent; import com.willwinder.universalgcodesender.model.events.SettingChangedEvent; +import com.willwinder.universalgcodesender.pendantui.html.StaticConfig; +import com.willwinder.universalgcodesender.pendantui.v1.AppV1Config; +import com.willwinder.universalgcodesender.pendantui.v1.ws.EventsSocket; +import com.willwinder.universalgcodesender.services.JogService; +import jakarta.ws.rs.core.UriBuilder; import net.glxn.qrgen.QRCode; import net.glxn.qrgen.image.ImageType; -import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketServletContainerInitializer; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.handler.DefaultHandler; -import org.eclipse.jetty.server.handler.HandlerList; -import org.eclipse.jetty.server.handler.ResourceHandler; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; +import org.glassfish.jersey.jetty.JettyHttpContainerFactory; +import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.servlet.ServletContainer; import java.io.ByteArrayOutputStream; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; -import java.net.URL; +import java.net.URI; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; @@ -51,55 +54,37 @@ This file is part of Universal Gcode Sender (UGS). * @author bobj */ public class PendantUI implements UGSEventListener { - private BackendAPI backendAPI; - private Server server = null; - private int port = 8080; + public static final String WEBSOCKET_CONTEXT_PATH = "/ws/v1"; + public static final String API_CONTEXT_PATH = "/api/v1"; private static final Logger LOG = Logger.getLogger(PendantUI.class.getSimpleName()); + private final JogService jogService; + private final BackendAPI backendAPI; + private int port = 8080; + private Server server; public PendantUI(BackendAPI backendAPI) { this.backendAPI = backendAPI; backendAPI.addUGSEventListener(this); - BackendAPIFactory.getInstance().register(backendAPI); + jogService = new JogService(backendAPI); + BackendProvider.register(backendAPI); } - public Resource getBaseResource(String directory) { - try { - URL res = getClass().getResource(directory); - return Resource.newResource(res); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** * Launches the local web server. * * @return the url for the pendant interface */ public List start() { - int port = backendAPI.getSettings().getPendantPort(); - server = new Server(port); + port = backendAPI.getSettings().getPendantPort(); + URI baseUri = UriBuilder.fromUri("http://localhost/").port(port).build(); - ResourceHandler staticResourceHandler = new ResourceHandler(); - staticResourceHandler.setDirectoriesListed(true); - staticResourceHandler.setWelcomeFiles(new String[]{"index.html"}); - staticResourceHandler.setBaseResource(getBaseResource("/resources/ugs-pendant")); + server = JettyHttpContainerFactory.createServer(baseUri, false); + ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection(); + server.setHandler(contextHandlerCollection); - ContextHandler staticResourceHandlerContext = new ContextHandler(); - staticResourceHandlerContext.setContextPath("/"); - staticResourceHandlerContext.setHandler(staticResourceHandler); - - // Create a servlet servletContextHandler - ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); - servletContextHandler.setContextPath("/api"); - ServletHolder servletHolder = servletContextHandler.addServlet(ServletContainer.class, "/*"); - servletHolder.setInitOrder(1); - servletHolder.setInitParameter("javax.ws.rs.Application", AppConfig.class.getCanonicalName()); - - HandlerList handlers = new HandlerList(); - handlers.setHandlers(new Handler[]{servletContextHandler, staticResourceHandlerContext, new DefaultHandler()}); - server.setHandler(handlers); + contextHandlerCollection.addHandler(createResourceConfigHandler(new StaticConfig(), "")); + contextHandlerCollection.addHandler(createResourceConfigHandler(new AppV1Config(backendAPI, jogService), API_CONTEXT_PATH)); + contextHandlerCollection.addHandler(createWebSocketHandler(WEBSOCKET_CONTEXT_PATH)); try { server.start(); @@ -110,6 +95,25 @@ public List start() { return getUrlList(); } + private ServletContextHandler createResourceConfigHandler(ResourceConfig config, String path) { + ServletContainer servletContainer = new ServletContainer(config); + ServletHolder servletHolder = new ServletHolder(servletContainer); + ServletContextHandler servletContextHandler = new ServletContextHandler(); + servletContextHandler.setContextPath(path); + servletContextHandler.addServlet(servletHolder, "/*"); + return servletContextHandler; + } + + private ServletContextHandler createWebSocketHandler(String contextPath) { + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath(contextPath); + JakartaWebSocketServletContainerInitializer.configure(context, (servletContext, wsContainer) -> { + wsContainer.setDefaultMaxTextMessageBufferSize(65535); + wsContainer.addEndpoint(EventsSocket.class); + }); + return context; + } + /** * Unfortunately, this is not as simple as it seems... since you can have multiple addresses and some of those may not be available via wireless * @@ -131,8 +135,7 @@ public List getUrlList() { while (addressEnum.hasMoreElements()) { InetAddress addr = addressEnum.nextElement(); String hostAddress = addr.getHostAddress(); - if (!hostAddress.contains(":") && - !hostAddress.equals("127.0.0.1")) { + if (!hostAddress.contains(":") && !hostAddress.equals("127.0.0.1")) { String url = "http://" + hostAddress + ":" + port; ByteArrayOutputStream bout = QRCode.from(url).to(ImageType.PNG).stream(); out.add(new PendantURLBean(url, bout.toByteArray())); @@ -162,10 +165,6 @@ public BackendAPI getBackendAPI() { return backendAPI; } - public void setBackendAPI(BackendAPI backendAPI) { - this.backendAPI = backendAPI; - } - @Override public void UGSEvent(UGSEvent evt) { if (evt instanceof SettingChangedEvent) { diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticConfig.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticConfig.java new file mode 100644 index 0000000000..6cab16bd70 --- /dev/null +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticConfig.java @@ -0,0 +1,27 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.pendantui.html; + +import org.glassfish.jersey.server.ResourceConfig; + +public class StaticConfig extends ResourceConfig { + public StaticConfig() { + register(StaticResource.class); + } +} diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticResource.java new file mode 100644 index 0000000000..a633016cc6 --- /dev/null +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticResource.java @@ -0,0 +1,65 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.pendantui.html; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response; +import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; + +import java.io.InputStream; +import java.util.Objects; + +@Path("/") +public class StaticResource { + + public static final String RESOURCES_PATH = "/resources/ugs-pendant/%s"; + + private static String getMimeType(String path) { + String mimeType = "application/octet-stream"; + if (path.endsWith(".js")) { + mimeType = "text/javascript"; + } else if (path.endsWith(".html")) { + mimeType = "text/html"; + } else if (path.endsWith(".css")) { + mimeType = "text/css"; + } + return mimeType; + } + + @GET + public Response getIndex() throws Exception { + return getStaticResource(""); + } + + @GET + @Path("{path:.*\\.(jpg|gif|html|js|css|ico)$}") + public Response getStaticResource(@PathParam("path") String path) throws Exception { + if (path.equalsIgnoreCase("")) { + path = "index.html"; + } + + InputStream resource = StaticResource.class.getResourceAsStream(String.format(RESOURCES_PATH, path)); + String mimeType = getMimeType(path); + return Objects.isNull(resource) ? Response.status(NOT_FOUND).build() : + Response.ok().entity(resource).header(HttpHeaders.CONTENT_TYPE, mimeType).build(); + } +} diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/AppConfig.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/AppV1Config.java similarity index 51% rename from ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/AppConfig.java rename to ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/AppV1Config.java index 97478d7f56..b7d8dd26c5 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/AppConfig.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/AppV1Config.java @@ -1,6 +1,26 @@ -package com.willwinder.universalgcodesender.pendantui; +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.pendantui.v1; import com.willwinder.universalgcodesender.model.BackendAPI; +import com.willwinder.universalgcodesender.pendantui.ExceptionMapper; +import com.willwinder.universalgcodesender.pendantui.html.StaticResource; import com.willwinder.universalgcodesender.pendantui.v1.resources.FilesResource; import com.willwinder.universalgcodesender.pendantui.v1.resources.MachineResource; import com.willwinder.universalgcodesender.pendantui.v1.resources.MacrosResource; @@ -8,16 +28,13 @@ import com.willwinder.universalgcodesender.pendantui.v1.resources.StatusResource; import com.willwinder.universalgcodesender.pendantui.v1.resources.TextResource; import com.willwinder.universalgcodesender.services.JogService; -import org.glassfish.hk2.utilities.binding.AbstractBinder; +import org.glassfish.jersey.internal.inject.AbstractBinder; import org.glassfish.jersey.media.multipart.MultiPartFeature; import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.server.wadl.WadlFeature; -import javax.ws.rs.ApplicationPath; - -@ApplicationPath("/api") -public class AppConfig extends ResourceConfig { - public AppConfig() { - register(ExceptionMapper.class); +public class AppV1Config extends ResourceConfig { + public AppV1Config(BackendAPI backendAPI, JogService jogService) { register(StatusResource.class); register(MachineResource.class); @@ -26,9 +43,9 @@ public AppConfig() { register(SettingsResource.class); register(FilesResource.class); register(MultiPartFeature.class); - - BackendAPI backendAPI = BackendAPIFactory.getInstance().getBackendAPI(); - JogService jogService = new JogService(backendAPI); + register(WadlFeature.class); + register(StaticResource.class); + register(ExceptionMapper.class); register(new AbstractBinder() { @Override diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/model/Event.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/model/Event.java new file mode 100644 index 0000000000..b30e199f04 --- /dev/null +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/model/Event.java @@ -0,0 +1,42 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.pendantui.v1.model; + +import com.willwinder.universalgcodesender.model.UGSEvent; + +import java.io.Serializable; + +public class Event implements Serializable { + private final String eventType; + + private final UGSEvent event; + + public Event(UGSEvent event) { + this.eventType = event.getClass().getSimpleName(); + this.event = event; + } + + public String getEventType() { + return eventType; + } + + public UGSEvent getEvent() { + return event; + } +} diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/FilesResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/FilesResource.java index 650c0b380a..2ebfe45775 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/FilesResource.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/FilesResource.java @@ -1,26 +1,44 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ package com.willwinder.universalgcodesender.pendantui.v1.resources; import com.willwinder.universalgcodesender.model.BackendAPI; import com.willwinder.universalgcodesender.pendantui.v1.model.WorkspaceFileList; +import jakarta.inject.Inject; import org.apache.commons.io.IOUtils; import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataParam; -import javax.inject.Inject; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; import java.io.File; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.List; -@Path("/v1/files") +@Path("/files") public class FilesResource { @Inject diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MachineResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MachineResource.java index a2ba647299..0288fd47f8 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MachineResource.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MachineResource.java @@ -1,3 +1,21 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ package com.willwinder.universalgcodesender.pendantui.v1.resources; import com.google.gson.JsonObject; @@ -13,17 +31,17 @@ import com.willwinder.universalgcodesender.utils.FirmwareUtils; import com.willwinder.universalgcodesender.utils.Settings; import com.willwinder.universalgcodesender.utils.SettingsFactory; +import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.NotAcceptableException; +import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; -import javax.inject.Inject; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.NotAcceptableException; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; import java.io.BufferedReader; import java.io.StringReader; import java.util.Arrays; @@ -31,7 +49,7 @@ import java.util.Optional; import java.util.stream.Collectors; -@Path("/v1/machine") +@Path("/machine") public class MachineResource { @Inject @@ -92,7 +110,7 @@ public List getBaudRateList() { @GET @Path("getSelectedBaudRate") @Produces(MediaType.APPLICATION_JSON) - public String getSelectedFBaudRate() { + public String getSelectedBaudRate() { JsonObject jsonObject = new JsonObject(); jsonObject.add("selectedBaudRate", new JsonPrimitive(SettingsFactory.loadSettings().getPortRate())); return jsonObject.toString(); diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MacrosResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MacrosResource.java index f6ad34b6b3..2afd82dab2 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MacrosResource.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MacrosResource.java @@ -1,30 +1,44 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ package com.willwinder.universalgcodesender.pendantui.v1.resources; import com.willwinder.universalgcodesender.MacroHelper; import com.willwinder.universalgcodesender.model.BackendAPI; import com.willwinder.universalgcodesender.pendantui.v1.model.Macro; -import com.willwinder.universalgcodesender.services.JogService; import com.willwinder.universalgcodesender.utils.SettingsFactory; +import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; -import javax.inject.Inject; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; import java.util.List; import java.util.stream.Collectors; -@Path("/v1/macros") +@Path("/macros") public class MacrosResource { @Inject private BackendAPI backendAPI; - @Inject - private JogService jogService; - @GET @Path("getMacroList") @Produces(MediaType.APPLICATION_JSON) diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/SettingsResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/SettingsResource.java index d2648adc65..ef75fe226c 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/SettingsResource.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/SettingsResource.java @@ -1,18 +1,34 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ package com.willwinder.universalgcodesender.pendantui.v1.resources; import com.willwinder.universalgcodesender.model.BackendAPI; import com.willwinder.universalgcodesender.pendantui.v1.model.Settings; +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; -import javax.inject.Inject; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -@Path("/v1/settings") +@Path("/settings") public class SettingsResource { - @Inject private BackendAPI backendAPI; diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/StatusResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/StatusResource.java index 3a1d61c78c..f643719584 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/StatusResource.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/StatusResource.java @@ -1,3 +1,21 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ package com.willwinder.universalgcodesender.pendantui.v1.resources; import com.willwinder.universalgcodesender.IController; @@ -6,14 +24,13 @@ import com.willwinder.universalgcodesender.model.BackendAPI; import com.willwinder.universalgcodesender.model.UnitUtils; import com.willwinder.universalgcodesender.pendantui.v1.model.Status; +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; -import javax.inject.Inject; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -@Path("/v1/status") +@Path("/status") public class StatusResource { @Inject diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/TextResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/TextResource.java index d84735aebc..72c94ce63d 100644 --- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/TextResource.java +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/TextResource.java @@ -1,14 +1,32 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ package com.willwinder.universalgcodesender.pendantui.v1.resources; import com.willwinder.universalgcodesender.i18n.Localization; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; import java.util.Map; -@Path("/v1/text") +@Path("/text") public class TextResource { @GET @Path("getTexts") diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/ws/EventsSocket.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/ws/EventsSocket.java new file mode 100644 index 0000000000..ff007597d3 --- /dev/null +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/ws/EventsSocket.java @@ -0,0 +1,89 @@ +/* + Copyright 2023 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ + +package com.willwinder.universalgcodesender.pendantui.v1.ws; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.willwinder.universalgcodesender.listeners.UGSEventListener; +import com.willwinder.universalgcodesender.model.UGSEvent; +import com.willwinder.universalgcodesender.pendantui.BackendProvider; +import com.willwinder.universalgcodesender.pendantui.v1.model.Event; +import jakarta.websocket.ClientEndpoint; +import jakarta.websocket.OnClose; +import jakarta.websocket.OnError; +import jakarta.websocket.OnOpen; +import jakarta.websocket.Session; +import jakarta.websocket.server.ServerEndpoint; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +@ClientEndpoint +@ServerEndpoint(value = "/events") +public class EventsSocket implements UGSEventListener { + + private static final Logger LOGGER = Logger.getLogger(EventsSocket.class.getSimpleName()); + private final Map sessions = new ConcurrentHashMap<>(); + private final Gson gson; + + public EventsSocket() { + gson = new GsonBuilder().serializeSpecialFloatingPointValues().create(); + if (BackendProvider.getBackendAPI() != null) { + BackendProvider.getBackendAPI().addUGSEventListener(this); + } + } + + @OnOpen + public void onWebSocketConnect(Session session) { + sessions.put(session.getId(), session); + LOGGER.info("WebSocket Connected: " + session.getId()); + } + + @OnClose + public void onWebSocketClose(Session session) { + sessions.remove(session.getId()); + LOGGER.info("WebSocket Closed: " + session.getId()); + } + + @OnError + public void onWebSocketError(Session session, Throwable cause) { + sessions.remove(session.getId()); + LOGGER.log(Level.WARNING, "WebSocket Closed: " + session.getId(), cause); + } + + @Override + public void UGSEvent(UGSEvent evt) { + try { + String data = gson.toJson(new Event(evt)).replaceAll(":NaN", ":null"); + sessions.values().forEach(session -> { + try { + session.getBasicRemote().sendText(data); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/ugs-platform/ugs-platform-ugslib/pom.xml b/ugs-platform/ugs-platform-ugslib/pom.xml index 3608c454e5..f8fc43f001 100644 --- a/ugs-platform/ugs-platform-ugslib/pom.xml +++ b/ugs-platform/ugs-platform-ugslib/pom.xml @@ -133,10 +133,14 @@ org.apache.commons.codec.binary org.apache.commons.io org.apache.commons.lang3 - javax.xml.bind - javax.xml.bind.annotation - javax.xml.bind.annotation.adapters + jakarta.activation + jakarta.xml.bind + jakarta.xml.bind.annotation + jakarta.xml.bind.annotation.adapters org.openjdk.nashorn.* + org.slf4j + org.slf4j.helpers + org.slf4j.spi