Compare commits

..

1 commit

Author SHA1 Message Date
311eb0c24e Update actions/upload-artifact action to v4 2025-02-15 16:13:52 +00:00
30 changed files with 151 additions and 298 deletions

View file

@ -1,22 +0,0 @@
name: Build
on:
push:
paths:
- .github/workflows/build.yml
- build.gradle
- settings.gradle
- src/**
- launcher/build.gradle
- launcher/src/**
workflow_dispatch:
jobs:
build:
runs-on: antville
steps:
- uses: actions/checkout@v4
- name: Compile with Gradle
run: ./gradlew :compileJava

View file

@ -1,39 +1,15 @@
name: Deploy name: Deploy (Production)
on: on: workflow_dispatch
workflow_dispatch:
inputs:
hostname:
description: Hostname
type: string
required: true
default: antville.org
jobs: jobs:
stage: deploy:
runs-on: antville runs-on: antville
environment: environment:
name: production name: antville.org
url: ${{ inputs.hostname }} url: https://antville.org
steps: steps:
- uses: actions/checkout@v4 - name: Copy files to production server
run: ssh staging-server deploy-helma
- name: Build with Gradle
run: ./gradlew installDist
- name: Copy build files to server
run: |
rsync ./build/install/helma/ ${{ inputs.hostname }}:./ \
--verbose --archive --delete --compress \
--filter '+ /bin' \
--filter '+ /extras' \
--filter '+ /launcher.jar' \
--filter '- /lib/ext' \
--filter '+ /lib' \
--filter '+ /modules' \
--filter '- /*'
- name: Restart Helma
run: ssh ${{ inputs.hostname }} restart

View file

@ -9,27 +9,16 @@ permissions:
contents: write contents: write
jobs: jobs:
release: build:
runs-on: antville runs-on: antville
env: env:
GH_TOKEN: ${{ secrets.GH_TOKEN }} GH_TOKEN: ${{ github.token }}
LC_TIME: en_US.UTF-8 LC_TIME: en_US.UTF-8
TODAY: $(date +'%d %b %Y')
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Create release notes
id: create_release_notes
run: |
release_notes=$(npx git-cliff@latest --latest)
# Write the release notes as a heredoc to the workflow output
# ⚠️ No white space around `<<` is crucial!
echo "release_notes<<.eot0x03" >> $GITHUB_OUTPUT
echo "$release_notes" >> $GITHUB_OUTPUT
echo ".eot0x03" >> $GITHUB_OUTPUT
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew assembleDist run: ./gradlew assembleDist
@ -40,20 +29,23 @@ jobs:
direction: upload direction: upload
url: https://code.host.antville.org url: https://code.host.antville.org
token: ${{ github.token }} token: ${{ github.token }}
title: Helma ${{ github.ref_name }} title: ${{ env.TODAY }}
#tag: $(date +'%Y.%m.%d')
release-dir: build/distributions release-dir: build/distributions
release-notes: ${{ steps.create_release_notes.outputs.release_notes }} release-notes-assistant: true
verbose: true verbose: true
- name: Create release at GitHub - name: Create release at GitHub
# FIXME: Currently only outputs gh command; adapt for Forgejo
run: | run: |
gh release create "$GITHUB_REF_NAME" \ echo gh release create "$GITHUB_REF_NAME" \
--repo "$GITHUB_REPOSITORY" \ --repo "$GITHUB_REPOSITORY" \
--title "Helma ${{ github.ref_name }}" \ --title "$(date +'%d %b %Y')" \
--notes "${{ steps.create_release_notes.outputs.release_notes }}" --generate-notes
- name: Upload release assets to GitHub - name: Upload release assets to GitHub
# FIXME: Currently only outputs gh command; adapt for Forgejo
run: | run: |
gh release upload "$GITHUB_REF_NAME" build/distributions/helma-*.* \ echo gh release upload "$GITHUB_REF_NAME" \
--repo "$GITHUB_REPOSITORY" \ build/distributions/helma-*.* \
--clobber --clobber

View file

@ -37,7 +37,7 @@ jobs:
- name: Save log file - name: Save log file
# FIXME: v4 of this action causes an error on Forgejo (“You must configure a GitHub token”) # FIXME: v4 of this action causes an error on Forgejo (“You must configure a GitHub token”)
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
if: always() if: always()
with: with:
name: renovate-log.ndjson name: renovate-log.ndjson

32
.github/workflows/stage.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: Deploy (Staging)
on: workflow_dispatch
jobs:
stage:
runs-on: antville
environment:
name: stage
url: ${{ vars.stage_url }}
steps:
- uses: actions/checkout@v4
- name: Build with Gradle
run: ./gradlew installDist
- name: Publish to staging server
run: |
rsync ./build/install/helma/ staging-server:./ \
--verbose --archive --delete --compress \
--filter '+ /bin' \
--filter '+ /extras' \
--filter '+ /launcher.jar' \
--filter '- /lib/ext' \
--filter '+ /lib' \
--filter '+ /modules' \
--filter '- /*'
- name: Restart Helma
run: ssh staging-server restart

32
.gitignore vendored
View file

@ -1,30 +1,22 @@
# Generally ignore hidden files .gradle
.* .idea
.settings
build
# Manage some Codium configuration /apps
.vscode/*
!.vscode
!.vscode/extensions.json
!.vscode/launch.json
!.vscode/settings.json
!.vscode/tasks.json
# Ignore files created during build or run
/bin /bin
/backups /backups
build /db
/docs /docs
/extras
/lib /lib
/licenses /licenses
/log /log
# Ignore files managed in src/dist
/*.properties
/apps
/db
/extras
/launcher.jar
/static /static
# Manage Gradle configuration /*.properties
/launcher.jar
/passwd
/start.*
!/gradle.properties !/gradle.properties

View file

@ -1 +1 @@
17 11.0

21
.vscode/launch.json vendored
View file

@ -1,21 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Current File",
"request": "launch",
"mainClass": "${file}"
},
{
"type": "java",
"name": "Debug",
"request": "launch",
"mainClass": "helma.main.Server",
"projectName": "helma_"
}
]
}

View file

@ -1,6 +1,6 @@
# License # License
Copyright (c) 1999-2025 Helma Project. All rights reserved. Copyright (c) 1999-2008 Helma Project. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions

View file

@ -2,8 +2,8 @@
## TL;DR ## TL;DR
- Make sure you have Java 17 or higher installed - Make sure you have Java 11 or higher installed
- Download and unpack the [latest release](https://code.host.antville.org/antville/helma/releases) - Download and unpack the [latest release](https://github.com/antville/helma/releases)
- Invoke `./bin/helma`, resp. `./bin/helma.bat`, depending on your platform - Invoke `./bin/helma`, resp. `./bin/helma.bat`, depending on your platform
- Direct your web browser to <http://localhost:8080> - Direct your web browser to <http://localhost:8080>

View file

@ -18,8 +18,8 @@ allprojects {
apply plugin: 'java' apply plugin: 'java'
java { java {
sourceCompatibility = JavaVersion.VERSION_17 sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_11
} }
repositories { repositories {
@ -42,6 +42,15 @@ if (JavaVersion.current().isJava8Compatible()) {
} }
} }
sourceSets {
main {
java {
// Sources in `src` will be available here after processing
srcDirs = ["$buildDir/src/main/java"]
}
}
}
configurations { configurations {
// Wrapping implementation because it does not allow access to its files // Wrapping implementation because it does not allow access to its files
// (i.e. cannot be resolved) // (i.e. cannot be resolved)
@ -49,17 +58,16 @@ configurations {
} }
dependencies { dependencies {
implementation 'com.google.code.gson:gson:2.12.1' implementation 'com.google.code.gson:gson:2.11.0'
implementation 'commons-codec:commons-codec:1.18.0' implementation 'commons-codec:commons-codec:1.17.1'
implementation 'org.apache.commons:commons-fileupload2-core:2.0.0-M2' implementation 'commons-fileupload:commons-fileupload:1.5'
implementation 'org.apache.commons:commons-fileupload2-jakarta:2.0.0-M1' implementation 'commons-logging:commons-logging:1.3.4'
implementation 'commons-logging:commons-logging:1.3.5'
implementation 'commons-net:commons-net:3.11.1' implementation 'commons-net:commons-net:3.11.1'
implementation 'com.sun.mail:javax.mail:1.6.2' implementation 'com.sun.mail:javax.mail:1.6.2'
implementation 'jakarta.servlet:jakarta.servlet-api:5.0.0' implementation 'javax.servlet:javax.servlet-api:4.0.1'
implementation 'org.ccil.cowan.tagsoup:tagsoup:1.2.1' implementation 'org.ccil.cowan.tagsoup:tagsoup:1.2.1'
implementation 'org.eclipse.jetty.ee9:jetty-ee9-servlet:12.0.19' implementation 'org.eclipse.jetty:jetty-servlet:9.4.56.v20240826'
implementation 'org.eclipse.jetty:jetty-xml:12.0.19' implementation 'org.eclipse.jetty:jetty-xml:9.4.56.v20240826'
implementation 'org.mozilla:rhino-all:1.8.0' implementation 'org.mozilla:rhino-all:1.8.0'
implementation 'org.sejda.imageio:webp-imageio:0.1.6' implementation 'org.sejda.imageio:webp-imageio:0.1.6'
implementation 'xerces:xercesImpl:2.12.2' implementation 'xerces:xercesImpl:2.12.2'
@ -148,11 +156,9 @@ installDist {
dependsOn build dependsOn build
} }
def processSource = tasks.register('processSource', Sync) { tasks.register('processSource', Sync) {
def gitOutput = new ByteArrayOutputStream() def gitOutput = new ByteArrayOutputStream()
outputs.dir "${project.buildDir}/src"
exec { exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD' commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = gitOutput standardOutput = gitOutput
@ -167,11 +173,9 @@ def processSource = tasks.register('processSource', Sync) {
.replaceAll('__builddate__', new Date().format("d MMM yyyy")) .replaceAll('__builddate__', new Date().format("d MMM yyyy"))
.replaceAll('__commithash__', gitOutput.toString().trim()) .replaceAll('__commithash__', gitOutput.toString().trim())
.replaceAll('__version__', version) .replaceAll('__version__', version)
} into outputs.files.singleFile } into "${project.buildDir}/src"
} }
tasks.compileJava.source = processSource.map { it.outputs.files }
tasks.register('update') { tasks.register('update') {
dependsOn installDist dependsOn installDist

View file

@ -1,52 +0,0 @@
# git-cliff ~ default configuration file
# https://git-cliff.org/docs/configuration
#
# Lines starting with "#" are comments.
# Configuration options are organized into tables and keys.
# See documentation for more information on available options.
[changelog]
trim = true
header = "## Changes"
body = """
{% for group, commits in commits | filter(attribute="merge_commit") | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
* [<tt>{{ commit.id | split(pat="") | slice(end=11) | join() }}</tt>]\
(https://code.host.antville.org/antville/helma/commit/{{ commit.id }}) \
{% if commit.breaking %}**Breaking:** {% endif %}\
{{ commit.message | split(pat="\\n") | first | upper_first | escape }}\
{% endfor %}
{% endfor %}
**Full Changelog:** [{{ previous.version }} {{ version }}]\
(https://code.host.antville.org/antville/helma/compare/\
{{ previous.version | urlencode }}..{{ version | urlencode }})\n\n
"""
footer = """
Generated by [git-cliff](https://git-cliff.org/).
"""
[git]
conventional_commits = false
filter_commits = false
filter_unconventional = false
protect_breaking_commits = false
sort_commits = "newest"
split_commits = false
topo_order = false
commit_parsers = [
{ message = "^Apply \\d+ suggestion", skip = true },
{ message = "^Merge .*(branch|dependabot|dependency|renovate)", skip = true },
{ message = "^Lock file maintenance", skip = true },
{ message = "yarn\\.lock", skip = true },
{ message = "^[Ff]ix", group = "<!-- 0 --> 🐛 Bug Fixes" },
{ field = "author.name", pattern = "[Rr]enovate|[Dd]ependabot", group = "<!-- 3 --> 📦 Dependency Updates" },
{ message = "^Merge pull request", group = "<!-- 1 --> 🔀 Merges" },
{ message = ".*", group = "<!-- 2 --> Uncategorized" },
]

Binary file not shown.

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

6
gradlew vendored
View file

@ -114,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH="\\\"\\\"" CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@ -205,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.
@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.

4
gradlew.bat vendored
View file

@ -70,11 +70,11 @@ goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH= set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View file

@ -16,6 +16,3 @@ project(':modules').projectDir = file('modules/helma')
project(':jala').projectDir = file('modules/jala') project(':jala').projectDir = file('modules/jala')
project(':hopKit').projectDir = file('modules/jala/util/HopKit') project(':hopKit').projectDir = file('modules/jala/util/HopKit')
project(':test').projectDir = file('modules/jala/util/Test') project(':test').projectDir = file('modules/jala/util/Test')
// Rename this project to prevent redundancy and renaming of main project (VSC does not care, though)
project(':modules').name = 'modules'

View file

@ -1,21 +0,0 @@
#!/bin/sh
# Use this script as forced command of an authorized SSH key:
# command="/home/helma/extras/deploy.sh" ssh-ed25519 AAAAC3NzaC…
case "$SSH_ORIGINAL_COMMAND" in
ping)
echo pong
;;
restart)
printf 'Restarting Helma… '
sudo /bin/systemctl restart helma
printf '%s\n' 'done.'
;;
*)
# Allow any rsync command but restrict it to the installation directory
rrsync -wo /home/helma
;;
esac

View file

@ -17,7 +17,7 @@
package helma.framework; package helma.framework;
import java.io.Serializable; import java.io.Serializable;
import jakarta.servlet.http.Cookie; import javax.servlet.http.Cookie;
/** /**
* Cookie Transmitter. A simple, serializable representation * Cookie Transmitter. A simple, serializable representation

View file

@ -16,12 +16,12 @@
package helma.framework; package helma.framework;
import jakarta.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map; import java.util.Map;
/** /**
* *
*/ */
public class RequestBean implements Serializable { public class RequestBean implements Serializable {
private static final long serialVersionUID = -6826881712426326687L; private static final long serialVersionUID = -6826881712426326687L;
@ -89,7 +89,7 @@ public class RequestBean implements Serializable {
* @return the header value, or null * @return the header value, or null
*/ */
public String getHeader(String name) { public String getHeader(String name) {
return req.getHeader(name); return req.getHeader(name);
} }
/** /**

View file

@ -19,9 +19,9 @@ package helma.framework;
import helma.util.SystemMap; import helma.util.SystemMap;
import helma.util.StringUtils; import helma.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Cookie; import javax.servlet.http.Cookie;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;

View file

@ -19,7 +19,7 @@ package helma.framework;
import helma.objectmodel.db.Transactor; import helma.objectmodel.db.Transactor;
import helma.scripting.ScriptingException; import helma.scripting.ScriptingException;
import jakarta.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.Serializable; import java.io.Serializable;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.PrintWriter; import java.io.PrintWriter;

View file

@ -21,7 +21,7 @@ import helma.framework.core.Application;
import helma.util.*; import helma.util.*;
import helma.scripting.ScriptingException; import helma.scripting.ScriptingException;
import jakarta.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.*; import java.io.*;
import java.security.*; import java.security.*;
import java.util.*; import java.util.*;

View file

@ -19,13 +19,11 @@ import java.util.Vector;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.xmlrpc.XmlRpcHandler; import org.apache.xmlrpc.XmlRpcHandler;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.ee9.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.ee9.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.ResourceFactory;
import helma.framework.core.Application; import helma.framework.core.Application;
import helma.framework.repository.FileRepository; import helma.framework.repository.FileRepository;
@ -483,29 +481,23 @@ public class ApplicationManager implements XmlRpcHandler {
// if there is a static direcory specified, mount it // if there is a static direcory specified, mount it
if (this.staticDir != null) { if (this.staticDir != null) {
String staticPath = getAbsoluteFile(this.staticDir).getCanonicalPath();
getLogger().info("Serving static from " + staticPath); File staticContent = getAbsoluteFile(this.staticDir);
getLogger().info("Serving static from " + staticContent.getPath());
getLogger().info("Mounting static at " + staticMountpoint); getLogger().info("Mounting static at " + staticMountpoint);
ResourceHandler rhandler = new ResourceHandler(); ResourceHandler rhandler = new ResourceHandler();
rhandler.setBaseResource(ResourceFactory.of(rhandler).newResource(staticPath)); rhandler.setResourceBase(staticContent.getPath());
rhandler.setWelcomeFiles(staticHome); rhandler.setWelcomeFiles(staticHome);
ContextHandler staticContext = new ContextHandler(); staticContext = ApplicationManager.this.context.addContext(staticMountpoint, ""); //$NON-NLS-1$
staticContext.setContextPath(staticMountpoint);
staticContext.setHandler(rhandler); staticContext.setHandler(rhandler);
ApplicationManager.this.context.addHandler(staticContext);
staticContext.start(); staticContext.start();
} }
// I hope I am correct assuming Helma does not need Jettys session management, but using appContext = new ServletContextHandler(context, pathPattern, true, true);
// `ServletContextHandler.SESSIONS` causes an exception: Shared scheduler not started
appContext = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
appContext.setContextPath(pathPattern);
context.addHandler(appContext);
Class servletClass = servletClassName == null ? Class servletClass = servletClassName == null ?
EmbeddedServletClient.class : Class.forName(servletClassName); EmbeddedServletClient.class : Class.forName(servletClassName);
ServletHolder holder = new ServletHolder(servletClass); ServletHolder holder = new ServletHolder(servletClass);
@ -537,9 +529,10 @@ public class ApplicationManager implements XmlRpcHandler {
} }
if (protectedStaticDir != null) { if (protectedStaticDir != null) {
String protectedContent = getAbsoluteFile(protectedStaticDir).getCanonicalPath(); File protectedContent = getAbsoluteFile(protectedStaticDir);
appContext.setBaseResourceAsString(protectedContent); appContext.setResourceBase(protectedContent.getPath());
getLogger().info("Serving protected static from " + protectedContent); getLogger().info("Serving protected static from " +
protectedContent.getPath());
} }
// Remap the context paths and start // Remap the context paths and start
@ -563,9 +556,7 @@ public class ApplicationManager implements XmlRpcHandler {
// unbind from Jetty HTTP server // unbind from Jetty HTTP server
if (ApplicationManager.this.jetty != null) { if (ApplicationManager.this.jetty != null) {
if (this.appContext != null) { if (this.appContext != null) {
// Adding appContext to the ContextHandlerCollection works (see above) but removing it causes an exception of ApplicationManager.this.context.removeHandler(this.appContext);
// incompatible types: ServletContextHandler cannot be converted to Handler
//ApplicationManager.this.context.removeHandler(this.appContext);
this.appContext.stop(); this.appContext.stop();
this.appContext.destroy(); this.appContext.destroy();
this.appContext = null; this.appContext = null;

View file

@ -16,12 +16,11 @@
package helma.main; package helma.main;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.URLResourceFactory;
import org.eclipse.jetty.xml.XmlConfiguration; import org.eclipse.jetty.xml.XmlConfiguration;
import java.net.URL; import java.net.URL;
@ -37,20 +36,18 @@ public class JettyServer {
public static JettyServer init(Server server, ServerConfig config) throws IOException { public static JettyServer init(Server server, ServerConfig config) throws IOException {
File configFile = config.getConfigFile(); File configFile = config.getConfigFile();
if (configFile != null && configFile.exists()) { if (configFile != null && configFile.exists()) {
URLResourceFactory resourceFactory = new URLResourceFactory(); return new JettyServer(configFile.toURI().toURL());
Resource resource = resourceFactory.newResource(configFile.toURI());
return new JettyServer(resource);
} else if (config.hasWebsrvPort()) { } else if (config.hasWebsrvPort()) {
return new JettyServer(config.getWebsrvPort(), server); return new JettyServer(config.getWebsrvPort(), server);
} }
return null; return null;
} }
private JettyServer(Resource resource) throws IOException { private JettyServer(URL url) throws IOException {
http = new org.eclipse.jetty.server.Server(); http = new org.eclipse.jetty.server.Server();
try { try {
XmlConfiguration config = new XmlConfiguration(resource); XmlConfiguration config = new XmlConfiguration(url);
config.configure(http); config.configure(http);
} catch (IOException e) { } catch (IOException e) {
@ -62,7 +59,7 @@ public class JettyServer {
private JettyServer(InetSocketAddress webPort, Server server) private JettyServer(InetSocketAddress webPort, Server server)
throws IOException { throws IOException {
http = new org.eclipse.jetty.server.Server(); http = new org.eclipse.jetty.server.Server();
// start embedded web server if port is specified // start embedded web server if port is specified
@ -76,6 +73,7 @@ public class JettyServer {
connector.setHost(webPort.getAddress().getHostAddress()); connector.setHost(webPort.getAddress().getHostAddress());
connector.setPort(webPort.getPort()); connector.setPort(webPort.getPort());
connector.setIdleTimeout(30000); connector.setIdleTimeout(30000);
connector.setSoLingerTime(-1);
connector.setAcceptorPriorityDelta(0); connector.setAcceptorPriorityDelta(0);
connector.setAcceptQueueSize(0); connector.setAcceptQueueSize(0);
@ -102,13 +100,12 @@ public class JettyServer {
} }
private void openListeners() throws IOException { private void openListeners() throws IOException {
// opening the listener here allows us to run on privileged port 80 under jsvc // opening the listener here allows us to run on priviledged port 80 under jsvc
// even as non-root user, because init() is called with root privileges // even as non-root user, because init() is called with root privileges
// while start() will be called with the user we will actually run as // while start() will be called with the user we will actually run as
for (var connector : http.getConnectors()) { Connector[] connectors = http.getConnectors();
if (connector instanceof ServerConnector) { for (int i = 0; i < connectors.length; i++) {
((ServerConnector) connector).open(); ((ServerConnector) connectors[i]).open();
}
} }
} }
} }

View file

@ -21,7 +21,6 @@ import helma.framework.repository.FileResource;
import helma.framework.core.*; import helma.framework.core.*;
import helma.objectmodel.db.DbSource; import helma.objectmodel.db.DbSource;
import helma.util.*; import helma.util.*;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.xmlrpc.*; import org.apache.xmlrpc.*;
@ -153,8 +152,8 @@ public class Server implements Runnable {
String javaVersion = System.getProperty("java.version", "0"); String javaVersion = System.getProperty("java.version", "0");
int majorVersion = Integer.parseInt(javaVersion.split("\\.")[0]); int majorVersion = Integer.parseInt(javaVersion.split("\\.")[0]);
if (majorVersion < 17) { if (majorVersion < 11) {
System.err.println("This version of Helma requires Java 17 or greater."); System.err.println("This version of Helma requires Java 11 or greater.");
if (majorVersion == 0) { // don't think this will ever happen, but you never know if (majorVersion == 0) { // don't think this will ever happen, but you never know
System.err.println("Your Java Runtime did not provide a version number. Please update to a more recent version."); System.err.println("Your Java Runtime did not provide a version number. Please update to a more recent version.");

View file

@ -22,29 +22,18 @@ package helma.servlet;
import helma.framework.*; import helma.framework.*;
import helma.framework.core.Application; import helma.framework.core.Application;
import helma.util.*; import helma.util.*;
import java.io.*; import java.io.*;
import java.nio.charset.Charset; import java.util.*;
import java.nio.charset.UnsupportedCharsetException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.*; import javax.servlet.*;
import javax.servlet.http.*;
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload2.core.DiskFileItemFactory; import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload2.core.FileItem; import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload2.core.FileUploadException; import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.commons.fileupload2.core.FileUploadSizeException;
import org.apache.commons.fileupload2.core.ProgressListener;
import org.apache.commons.fileupload2.jakarta.JakartaServletDiskFileUpload;
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
import org.apache.commons.fileupload2.jakarta.JakartaServletRequestContext;
/** /**
* This is an abstract Hop servlet adapter. This class communicates with hop applications * This is an abstract Hop servlet adapter. This class communicates with hop applications
@ -229,9 +218,9 @@ public abstract class AbstractServletClient extends HttpServlet {
// read file uploads // read file uploads
List uploads = null; List uploads = null;
JakartaServletRequestContext reqcx = new JakartaServletRequestContext(request); ServletRequestContext reqcx = new ServletRequestContext(request);
if (JakartaServletFileUpload.isMultipartContent(reqcx)) { if (ServletFileUpload.isMultipartContent(reqcx)) {
// get session for upload progress monitoring // get session for upload progress monitoring
UploadStatus uploadStatus = getApplication().getUploadStatus(reqtrans); UploadStatus uploadStatus = getApplication().getUploadStatus(reqtrans);
try { try {
@ -239,7 +228,7 @@ public abstract class AbstractServletClient extends HttpServlet {
} catch (Exception upx) { } catch (Exception upx) {
log("Error in file upload", upx); log("Error in file upload", upx);
String message; String message;
boolean tooLarge = (upx instanceof FileUploadSizeException); boolean tooLarge = (upx instanceof FileUploadBase.SizeLimitExceededException);
if (tooLarge) { if (tooLarge) {
message = "File upload size exceeds limit of " + uploadLimit + " kB"; message = "File upload size exceeds limit of " + uploadLimit + " kB";
} else { } else {
@ -664,12 +653,12 @@ public abstract class AbstractServletClient extends HttpServlet {
map.put(name, newValues); map.put(name, newValues);
} }
protected List parseUploads(JakartaServletRequestContext reqcx, RequestTrans reqtrans, protected List parseUploads(ServletRequestContext reqcx, RequestTrans reqtrans,
final UploadStatus uploadStatus, String encoding) final UploadStatus uploadStatus, String encoding)
throws FileUploadException, UnsupportedCharsetException, IOException { throws FileUploadException, UnsupportedEncodingException {
// handle file upload // handle file upload
DiskFileItemFactory factory = DiskFileItemFactory.builder().get(); DiskFileItemFactory factory = new DiskFileItemFactory();
JakartaServletFileUpload upload = new JakartaServletFileUpload(factory); FileUpload upload = new FileUpload(factory);
// use upload limit for individual file size, but also set a limit on overall size // use upload limit for individual file size, but also set a limit on overall size
upload.setFileSizeMax(uploadLimit * 1024); upload.setFileSizeMax(uploadLimit * 1024);
upload.setSizeMax(totalUploadLimit * 1024); upload.setSizeMax(totalUploadLimit * 1024);
@ -692,7 +681,7 @@ public abstract class AbstractServletClient extends HttpServlet {
Object value; Object value;
// check if this is an ordinary HTML form element or a file upload // check if this is an ordinary HTML form element or a file upload
if (item.isFormField()) { if (item.isFormField()) {
value = item.getString(Charset.forName(encoding)); value = item.getString(encoding);
} else { } else {
value = new MimePart(item); value = new MimePart(item);
} }

View file

@ -19,7 +19,7 @@ package helma.servlet;
import helma.framework.*; import helma.framework.*;
import helma.framework.core.Application; import helma.framework.core.Application;
import helma.main.*; import helma.main.*;
import jakarta.servlet.*; import javax.servlet.*;
/** /**
* Servlet client that runs a Helma application for the embedded * Servlet client that runs a Helma application for the embedded

View file

@ -23,7 +23,7 @@ import helma.main.ServerConfig;
import helma.main.Server; import helma.main.Server;
import java.io.*; import java.io.*;
import jakarta.servlet.*; import javax.servlet.*;
import java.util.*; import java.util.*;
/** /**
@ -98,7 +98,7 @@ public final class StandaloneServletClient extends AbstractServletClient {
repositoryImpl = "helma.framework.repository.FileRepository"; repositoryImpl = "helma.framework.repository.FileRepository";
} }
} }
try { try {
Repository newRepository = (Repository) Class.forName(repositoryImpl) Repository newRepository = (Repository) Class.forName(repositoryImpl)
.getConstructor(parameters) .getConstructor(parameters)
@ -116,7 +116,7 @@ public final class StandaloneServletClient extends AbstractServletClient {
} }
} }
} }
// add app dir // add app dir
FileRepository appRep = new FileRepository(appDir); FileRepository appRep = new FileRepository(appDir);
log("adding repository: " + appDir); log("adding repository: " + appDir);

View file

@ -16,7 +16,7 @@
package helma.util; package helma.util;
import org.apache.commons.fileupload2.core.FileItem; import org.apache.commons.fileupload.FileItem;
import java.io.*; import java.io.*;
import java.util.Date; import java.util.Date;
@ -238,7 +238,7 @@ public class MimePart implements Serializable {
file = new File(base, filename); file = new File(base, filename);
if (fileItem != null) { if (fileItem != null) {
fileItem.write(file.toPath()); fileItem.write(file);
// null out fileItem, since calling write() may have moved the temp file // null out fileItem, since calling write() may have moved the temp file
fileItem = null; fileItem = null;
} else { } else {
@ -249,7 +249,7 @@ public class MimePart implements Serializable {
// return file name // return file name
return filename; return filename;
} catch (Exception x) { } catch (Exception x) {
System.err.println("Error in MimePart.writeToFile(): " + x); System.err.println("Error in MimePart.writeToFile(): " + x);
return null; return null;
} }
} }