diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml index cd109f1..b1a43a9 100644 --- a/.github/workflows/maven-ci.yml +++ b/.github/workflows/maven-ci.yml @@ -16,11 +16,11 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 11 + - name: Set up JDK 21 uses: actions/setup-java@v2 with: - java-version: 11 - distribution: 'adopt' + java-version: 21 + distribution: 'temurin' architecture: x64 - name: Cache Maven packages uses: actions/cache@v2 diff --git a/Dockerfile b/Dockerfile index a643e03..939d349 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM adoptopenjdk:11-jre-hotspot +FROM eclipse-temurin:21-jre-alpine LABEL description="Basic Proxy Facade for NTLM, Kerberos, SOCKS and Proxy Auto Config file proxies" LABEL maintainer="ecovaci" @@ -13,9 +13,9 @@ RUN chmod +x /opt/winfoom/docker-entrypoint.sh EXPOSE 3129 9999 -RUN groupadd -r winfoom && useradd -r -g winfoom winfoom +RUN addgroup -S winfoom && adduser -S -g winfoom winfoom -RUN mkdir /data && chown winfoom:winfoom /data +RUN mkdir /data && chown winfoom:winfoom /data && chown -R winfoom:winfoom /opt/winfoom USER winfoom diff --git a/README.md b/README.md index 4136bda..1740041 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ An example of such a facade for NTLM proxies is [CNTLM](http://cntlm.sourceforge ## Download Winfoom ### Download prepackaged To try out Winfoom without needing to download the source and package it, check out the [releases](https://github.com/ecovaci/winfoom/releases) for a prepackaged `winfoom-*.zip`. -Winfoom is a Java application and requires a Java Runtime Environment (at least v11). +Winfoom is a Java application and requires a Java Runtime Environment (at least v17). If it is not already installed on your system, you can download it from [AdoptOpenJDK](https://adoptopenjdk.net/) or, on Linux systems, use your package manager. @@ -39,7 +39,7 @@ to your system architecture, unzip it in the Winfoom directory and rename it to ### Build from source code If you decide to build the executable *jar* file from the source code, you would need these prerequisites: -* Java JDK 11(+) +* Java JDK 21+ (winfoom requires Java 17 to run, but JDK21 or higher is required to build) * Maven 3.x version (optional) First download the source code from [releases](https://github.com/ecovaci/winfoom/releases) and unzip it. diff --git a/pom.xml b/pom.xml index ae4ac59..17ae8fb 100644 --- a/pom.xml +++ b/pom.xml @@ -18,33 +18,31 @@ org.springframework.boot spring-boot-starter-parent - 2.6.4 + 3.2.2 org.kpax winfoom - 4.0.3 + 5.0.0-SNAPSHOT winfoom https://github.com/ecovaci/winfoom UTF-8 - 11 - 4.5.13 - 2.7 - 2.11.0 + 4.5.14 + 2.9.0 + 2.15.1 1.9.4 - 5.3.3 + 5.4.0 2.6.1.Final - 2.11.1 - 22.0.0.2 - 5.9.0 + 2.12.0 + 23.0.3 1.1.2 - 5.10.0 - 1.18.20 - 3.20.2 - 2.17.2 + 5.15.0 + 1.18.30 + 3.25.1 + 2.22.1 @@ -185,6 +183,45 @@ winfoom + + org.apache.maven.plugins + maven-compiler-plugin + + + compile-java-17 + + compile + + + 17 + + + + compile-java-21 + + compile + + + 21 + + ${project.basedir}/src/main/java21 + + true + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + + + + org.springframework.boot spring-boot-maven-plugin diff --git a/src/main/java/org/kpax/winfoom/api/ApiController.java b/src/main/java/org/kpax/winfoom/api/ApiController.java index 01060c5..08524c2 100644 --- a/src/main/java/org/kpax/winfoom/api/ApiController.java +++ b/src/main/java/org/kpax/winfoom/api/ApiController.java @@ -43,7 +43,7 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/org/kpax/winfoom/config/ProxyConfig.java b/src/main/java/org/kpax/winfoom/config/ProxyConfig.java index 5f9bdb4..418d275 100644 --- a/src/main/java/org/kpax/winfoom/config/ProxyConfig.java +++ b/src/main/java/org/kpax/winfoom/config/ProxyConfig.java @@ -34,8 +34,8 @@ import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; diff --git a/src/main/java/org/kpax/winfoom/config/SystemConfig.java b/src/main/java/org/kpax/winfoom/config/SystemConfig.java index 4f27702..d991363 100644 --- a/src/main/java/org/kpax/winfoom/config/SystemConfig.java +++ b/src/main/java/org/kpax/winfoom/config/SystemConfig.java @@ -20,7 +20,7 @@ import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.net.Socket; import java.net.SocketException; import java.util.List; diff --git a/src/main/java/org/kpax/winfoom/proxy/ProxyExecutorService.java b/src/main/java/org/kpax/winfoom/proxy/ProxyExecutorService.java index e3f679a..3e2adce 100644 --- a/src/main/java/org/kpax/winfoom/proxy/ProxyExecutorService.java +++ b/src/main/java/org/kpax/winfoom/proxy/ProxyExecutorService.java @@ -13,6 +13,7 @@ package org.kpax.winfoom.proxy; import lombok.extern.slf4j.Slf4j; +import org.kpax.winfoom.proxy.concurrent.ExecutorServiceFactory; import org.kpax.winfoom.proxy.listener.StopListener; import org.kpax.winfoom.util.functional.SingletonSupplier; import org.springframework.core.annotation.Order; @@ -21,7 +22,6 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; /** * A wrapper for {@link ThreadPoolExecutor} that forbids {@link #shutdown()}, {@link #shutdownNow()} @@ -32,13 +32,10 @@ @Component public class ProxyExecutorService implements ExecutorService, StopListener { - private final SingletonSupplier threadPoolSupplier; + private final SingletonSupplier threadPoolSupplier; public ProxyExecutorService() { - this.threadPoolSupplier = - new SingletonSupplier<>(() -> new ThreadPoolExecutor(0, Integer.MAX_VALUE, - 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), - new DefaultThreadFactory())); + this.threadPoolSupplier = new SingletonSupplier<>(() -> new ExecutorServiceFactory().get()); } public void execute(Runnable task) { @@ -102,42 +99,15 @@ public boolean isTerminated() { return threadPoolSupplier.hasValue() && threadPoolSupplier.get().isTerminated(); } + @Override + public void close() { + StopListener.super.close(); + } + @Override public void onStop() { log.debug("Reset the proxy executor service"); threadPoolSupplier.reset(ExecutorService::shutdownNow); } - public static class DefaultThreadFactory implements ThreadFactory { - private static final AtomicInteger poolNumber = new AtomicInteger(1); - private final ThreadGroup group; - private final AtomicInteger threadNumber = new AtomicInteger(1); - private final String namePrefix; - - public DefaultThreadFactory() { - SecurityManager securityManager = System.getSecurityManager(); - group = (securityManager != null) ? securityManager.getThreadGroup() : - Thread.currentThread().getThreadGroup(); - namePrefix = "pool-" + - poolNumber.getAndIncrement() + - "-thread-"; - } - - @Override - public Thread newThread(Runnable runnable) { - Thread thread = new Thread(group, runnable, - namePrefix + threadNumber.getAndIncrement(), - 0); - - // Make sure all threads are daemons! - if (!thread.isDaemon()) { - thread.setDaemon(true); - } - - if (thread.getPriority() != Thread.NORM_PRIORITY) { - thread.setPriority(Thread.NORM_PRIORITY); - } - return thread; - } - } } \ No newline at end of file diff --git a/src/main/java/org/kpax/winfoom/proxy/TunnelConnection.java b/src/main/java/org/kpax/winfoom/proxy/TunnelConnection.java index b827938..5015071 100644 --- a/src/main/java/org/kpax/winfoom/proxy/TunnelConnection.java +++ b/src/main/java/org/kpax/winfoom/proxy/TunnelConnection.java @@ -45,7 +45,7 @@ import org.kpax.winfoom.util.functional.ProxySingletonSupplier; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.io.IOException; import java.net.Socket; diff --git a/src/main/java/org/kpax/winfoom/proxy/concurrent/DefaultThreadFactory.java b/src/main/java/org/kpax/winfoom/proxy/concurrent/DefaultThreadFactory.java new file mode 100644 index 0000000..294e4cc --- /dev/null +++ b/src/main/java/org/kpax/winfoom/proxy/concurrent/DefaultThreadFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024. Eugen Covaci + * 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.kpax.winfoom.proxy.concurrent; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * A {@link ThreadFactory} for thread pools. + */ +public class DefaultThreadFactory implements ThreadFactory { + + private static final AtomicInteger poolNumber = new AtomicInteger(1); + private final ThreadGroup group; + private final AtomicInteger threadNumber = new AtomicInteger(1); + private final String namePrefix; + + public DefaultThreadFactory() { + SecurityManager securityManager = System.getSecurityManager(); + group = (securityManager != null) ? securityManager.getThreadGroup() : Thread.currentThread().getThreadGroup(); + namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; + } + + @Override + public Thread newThread(Runnable runnable) { + Thread thread = new Thread(group, runnable, namePrefix + threadNumber.getAndIncrement(), 0); + // Make sure all threads are daemons! + if (!thread.isDaemon()) { + thread.setDaemon(true); + } + if (thread.getPriority() != Thread.NORM_PRIORITY) { + thread.setPriority(Thread.NORM_PRIORITY); + } + return thread; + } + +} diff --git a/src/main/java/org/kpax/winfoom/proxy/concurrent/ExecutorServiceFactory.java b/src/main/java/org/kpax/winfoom/proxy/concurrent/ExecutorServiceFactory.java new file mode 100644 index 0000000..f522387 --- /dev/null +++ b/src/main/java/org/kpax/winfoom/proxy/concurrent/ExecutorServiceFactory.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024. Eugen Covaci + * 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.kpax.winfoom.proxy.concurrent; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +/** + * A factory which creates a thread pool executor. + */ +public class ExecutorServiceFactory implements Supplier { + + @Override + public ExecutorService get() { + return new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), + new DefaultThreadFactory()); + } + +} diff --git a/src/main/java/org/kpax/winfoom/view/AppFrame.java b/src/main/java/org/kpax/winfoom/view/AppFrame.java index 8419773..e04dc9a 100644 --- a/src/main/java/org/kpax/winfoom/view/AppFrame.java +++ b/src/main/java/org/kpax/winfoom/view/AppFrame.java @@ -26,7 +26,7 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.event.DocumentEvent; diff --git a/src/main/java21/org/kpax/winfoom/proxy/concurrent/ExecutorServiceFactory.java b/src/main/java21/org/kpax/winfoom/proxy/concurrent/ExecutorServiceFactory.java new file mode 100644 index 0000000..ac95529 --- /dev/null +++ b/src/main/java21/org/kpax/winfoom/proxy/concurrent/ExecutorServiceFactory.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024. Eugen Covaci + * 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.kpax.winfoom.proxy.concurrent; + +import java.util.concurrent.*; +import java.util.function.Supplier; + +/** + * A factory which creates a virtual thread executor. + */ +public class ExecutorServiceFactory implements Supplier { + + public ExecutorService get() { + ThreadFactory factory = Thread.ofVirtual() + .name("virtual-thread-", 0L) + .factory(); + return Executors.newThreadPerTaskExecutor(factory); + } + +}