diff --git a/pom.xml b/pom.xml index 01d4b20260..8e055b8af0 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ UTF-8 12.0.3 - 3.1.5 + 3.1.6 2.5.0 2.5.0 3.7.4 @@ -75,7 +75,7 @@ 1.2.2 4.13.2 2.2 - 3.4.1 + 3.5.3 0.10.1 1.4 5.2.0 diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/JettyHttpContainerFactory.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/JettyHttpContainerFactory.java new file mode 100644 index 0000000000..2abddce32f --- /dev/null +++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/JettyHttpContainerFactory.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package com.willwinder.universalgcodesender.pendantui; + +import jakarta.ws.rs.ProcessingException; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder; +import org.glassfish.jersey.jetty.JettyHttpContainer; +import org.glassfish.jersey.jetty.internal.LocalizationMessages; +import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler; +import org.glassfish.jersey.server.spi.Container; + +import java.net.URI; +import java.util.concurrent.ThreadFactory; + +/** + * Copied from glasfish source as the shaded variant will throw an unsupported exception by default. + *

+ * Factory for creating and starting Jetty server handlers. This returns + * a handle to the started server as {@link Server} instances, which allows + * the server to be stopped by invoking the {@link org.eclipse.jetty.server.Server#stop()} method. + *

+ * To start the server in HTTPS mode an {@link SslContextFactory} can be provided. + * This will be used to decrypt and encrypt information sent over the + * connected TCP socket channel. + * + * @author Arul Dhesiaseelan (aruld@acm.org) + * @author Marek Potociar + */ +public final class JettyHttpContainerFactory { + + private JettyHttpContainerFactory() { + } + + /** + * Creates a {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}. + * + * @param uri uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path + * segment will be used as context path, the rest will be ignored. + * @param start if set to false, server will not get started, which allows to configure the underlying transport + * layer, see above for details. + * @return newly created {@link Server}. + * + * @throws ProcessingException in case of any failure when creating a new Jetty {@code Server} instance. + * @throws IllegalArgumentException if {@code uri} is {@code null}. + */ + public static Server createServer(final URI uri, final boolean start) throws ProcessingException { + return createServer(uri, null, start); + } + + /** + * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that + * in turn manages all root resource and provider classes found by searching the + * classes referenced in the java classpath. + * + * @param uri the URI to create the http server. The URI scheme must be + * equal to {@code https}. The URI user information and host + * are ignored. If the URI port is not present then port + * {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be + * used. The URI path, query and fragment components are ignored. + * @param sslContextFactory this is the SSL context factory used to configure SSL connector + * @param start if set to false, server will not get started, this allows end users to set + * additional properties on the underlying listener. + * @return newly created {@link Server}. + * + * @throws ProcessingException in case of any failure when creating a new Jetty {@code Server} instance. + * @throws IllegalArgumentException if {@code uri} is {@code null}. + * @see JettyHttpContainer + */ + public static Server createServer(final URI uri, + final SslContextFactory.Server sslContextFactory, + final boolean start) { + if (uri == null) { + throw new IllegalArgumentException(LocalizationMessages.URI_CANNOT_BE_NULL()); + } + final String scheme = uri.getScheme(); + int defaultPort = Container.DEFAULT_HTTP_PORT; + + if (sslContextFactory == null) { + if (!"http".equalsIgnoreCase(scheme)) { + throw new IllegalArgumentException(LocalizationMessages.WRONG_SCHEME_WHEN_USING_HTTP()); + } + } else { + if (!"https".equalsIgnoreCase(scheme)) { + throw new IllegalArgumentException(LocalizationMessages.WRONG_SCHEME_WHEN_USING_HTTPS()); + } + defaultPort = Container.DEFAULT_HTTPS_PORT; + } + final int port = (uri.getPort() == -1) ? defaultPort : uri.getPort(); + + final Server server = new Server(new JettyConnectorThreadPool()); + final HttpConfiguration config = new HttpConfiguration(); + if (sslContextFactory != null) { + config.setSecureScheme("https"); + config.setSecurePort(port); + config.addCustomizer(new SecureRequestCustomizer()); + + final ServerConnector https = new ServerConnector(server, + new SslConnectionFactory(sslContextFactory, "http/1.1"), + new HttpConnectionFactory(config)); + https.setPort(port); + server.setConnectors(new Connector[]{https}); + + } else { + final ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(config)); + http.setPort(port); + server.setConnectors(new Connector[]{http}); + } + + if (start) { + try { + // Start the server. + server.start(); + } catch (final Exception e) { + throw new ProcessingException(LocalizationMessages.ERROR_WHEN_CREATING_SERVER(), e); + } + } + return server; + } + + // TODO: Use https://www.eclipse.org/jetty/javadoc/current/org/eclipse/jetty/util/thread/QueuedThreadPool.html + // #%3Cinit%3E(int,int,int,int,java.util.concurrent.BlockingQueue,java.lang.ThreadGroup,java.util.concurrent.ThreadFactory) + // + // Keeping this for backwards compatibility for the time being + private static final class JettyConnectorThreadPool extends QueuedThreadPool { + private final ThreadFactory threadFactory = new ThreadFactoryBuilder() + .setNameFormat("jetty-http-server-%d") + .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler()) + .build(); + + @Override + public Thread newThread(Runnable runnable) { + return threadFactory.newThread(runnable); + } + } +} 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 6ed4f98b84..84770e822f 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 @@ -34,7 +34,6 @@ This file is part of Universal Gcode Sender (UGS). import org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketServletContainerInitializer; import org.eclipse.jetty.server.Server; 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;