瀏覽代碼

maven updated and minor fixes

Jason Rivard 2 年之前
父節點
當前提交
adb5fec19f
共有 28 個文件被更改,包括 239 次插入420 次删除
  1. 3 4
      README.md
  2. 2 2
      data-service/pom.xml
  3. 2 2
      docker/pom.xml
  4. 8 8
      pom.xml
  5. 5 5
      server/pom.xml
  6. 0 1
      server/src/main/java/password/pwm/AppProperty.java
  7. 14 65
      server/src/main/java/password/pwm/PwmApplication.java
  8. 53 0
      server/src/main/java/password/pwm/PwmApplicationUtil.java
  9. 5 0
      server/src/main/java/password/pwm/http/ContextManager.java
  10. 2 2
      server/src/main/java/password/pwm/http/servlet/configeditor/ConfigEditorServlet.java
  11. 1 1
      server/src/main/java/password/pwm/http/servlet/setupresponses/SetupResponsesServlet.java
  12. 2 2
      server/src/main/java/password/pwm/svc/AbstractPwmService.java
  13. 0 11
      server/src/main/java/password/pwm/svc/db/DBConfiguration.java
  14. 1 1
      server/src/main/java/password/pwm/svc/db/DatabaseAccessorImpl.java
  15. 3 24
      server/src/main/java/password/pwm/svc/db/DatabaseService.java
  16. 98 234
      server/src/main/java/password/pwm/svc/db/JDBCDriverLoader.java
  17. 1 1
      server/src/main/java/password/pwm/svc/event/LocalDbAuditVault.java
  18. 10 4
      server/src/main/java/password/pwm/svc/userhistory/DatabaseUserHistory.java
  19. 8 7
      server/src/main/java/password/pwm/svc/userhistory/LdapXmlUserHistory.java
  20. 1 1
      server/src/main/java/password/pwm/svc/wordlist/AbstractWordlist.java
  21. 4 7
      server/src/main/java/password/pwm/util/PwmScheduler.java
  22. 7 7
      server/src/main/java/password/pwm/util/SampleDataGenerator.java
  23. 0 1
      server/src/main/resources/password/pwm/AppProperty.properties
  24. 2 1
      server/src/test/java/password/pwm/svc/event/LdapXmlUserHistoryTest.java
  25. 6 1
      server/src/test/java/password/pwm/util/macro/MacroTest.java
  26. 0 10
      webapp/pom.xml
  27. 0 17
      webapp/src/main/webapp/WEB-INF/jsp/admin-dashboard.jsp
  28. 1 1
      webapp/src/main/webapp/public/resources/js/main.js

+ 3 - 4
README.md

@@ -144,8 +144,7 @@ log, and runtime files.  Once PWM is configured, the initial web UI will prompt
 
 ### Java Executable
 The 'onejar' artifact released with PWM has an embedded tomcat instance, so you don't need to install tomcat to use this
-version.  You will be responsible for getting it to run as a service, and you won't be able to do any advanced tomcat
-configuration.  
+version.  It's ideal for testing and evaluating PWM.  You will be responsible for getting it to run as a service (if desired).  
 
 Requirements:
 * Java 11 JDK or better
@@ -158,7 +157,7 @@ Example for running onejar executable (with /pwm-applicationPath being the locat
 ```
 java -jar pwm-onejar-2.0.0.jar -applicationPath /pwm-applicationPath 
 ```
-By default the executable will remain attached to the console and listen for HTTPS connections on port 8443.
+By default, the executable will remain attached to the console and listen for HTTPS connections on port 8443.
 
 
 ### WAR
@@ -256,7 +255,7 @@ git clone https://github.com/pwm-project/pwm
 cd pwm
 mvnw.cmd clean verify
 ```
-On Windows we recommend using paths without spaces (including for the JDK directory).
+On Windows we recommend using paths without spaces for both PWM and JDK directory.
 
 Artifacts created:
 

+ 2 - 2
data-service/pom.xml

@@ -130,7 +130,7 @@
             <plugin>
                 <groupId>com.google.cloud.tools</groupId>
                 <artifactId>jib-maven-plugin</artifactId>
-                <version>3.3.1</version>
+                <version>3.3.2</version>
                 <executions>
                     <execution>
                         <id>make-docker-image</id>
@@ -234,7 +234,7 @@
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
-            <version>1.4.6</version>
+            <version>1.4.7</version>
         </dependency>
     </dependencies>
 </project>

+ 2 - 2
docker/pom.xml

@@ -34,7 +34,7 @@
             <plugin>
                 <groupId>com.google.cloud.tools</groupId>
                 <artifactId>jib-maven-plugin</artifactId>
-                <version>3.3.1</version>
+                <version>3.3.2</version>
                 <executions>
                     <execution>
                         <id>make-docker-image</id>
@@ -93,7 +93,7 @@
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>build-helper-maven-plugin</artifactId>
-                <version>3.3.0</version>
+                <version>3.4.0</version>
                 <executions>
                     <execution>
                         <id>attach-artifacts</id>

+ 8 - 8
pom.xml

@@ -180,7 +180,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-enforcer-plugin</artifactId>
-                <version>3.2.1</version>
+                <version>3.3.0</version>
                 <executions>
                     <execution>
                         <id>enforce-maven</id>
@@ -216,12 +216,12 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-checkstyle-plugin</artifactId>
-                <version>3.2.1</version>
+                <version>3.2.2</version>
                 <dependencies>
                     <dependency>
                         <groupId>com.puppycrawl.tools</groupId>
                         <artifactId>checkstyle</artifactId>
-                        <version>10.9.3</version>
+                        <version>10.11.0</version>
                     </dependency>
                 </dependencies>
                 <executions>
@@ -300,7 +300,7 @@
             <plugin>
                 <groupId>com.github.spotbugs</groupId>
                 <artifactId>spotbugs-maven-plugin</artifactId>
-                <version>4.7.3.3</version>
+                <version>4.7.3.4</version>
                 <dependencies>
                     <dependency>
                         <groupId>com.github.spotbugs</groupId>
@@ -310,7 +310,7 @@
                 </dependencies>
                 <configuration>
                     <skip>${spotbugs.skip}</skip>
-                    <fork>false</fork>
+                    <fork>true</fork>
                     <excludeFilterFile>${project.root.basedir}/build/spotbugs-exclude.xml</excludeFilterFile>
                     <includeTests>false</includeTests>
                     <effort>max</effort>
@@ -390,7 +390,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
-                    <version>3.0.0</version>
+                    <version>3.1.0</version>
                     <executions>
                         <execution>
                             <id>default-test</id>
@@ -460,13 +460,13 @@
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
-            <version>5.2.0</version>
+            <version>5.3.1</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>com.github.tomakehurst</groupId>
             <artifactId>wiremock</artifactId>
-            <version>3.0.0-beta-6</version>
+            <version>3.0.0-beta-8</version>
             <scope>test</scope>
         </dependency>
         <dependency>

+ 5 - 5
server/pom.xml

@@ -173,7 +173,7 @@
         <dependency>
             <groupId>com.github.ldapchai</groupId>
             <artifactId>ldapchai</artifactId>
-            <version>0.8.4</version>
+            <version>0.8.5</version>
         </dependency>
         <dependency>
             <groupId>org.jrivard.xmlchai</groupId>
@@ -183,7 +183,7 @@
         <dependency>
             <groupId>org.apache.directory.api</groupId>
             <artifactId>api-all</artifactId>
-            <version>2.1.2</version>
+            <version>2.1.3</version>
         </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
@@ -218,7 +218,7 @@
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
-            <version>1.4.6</version>
+            <version>1.4.7</version>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
@@ -259,7 +259,7 @@
         <dependency>
             <groupId>com.squareup.moshi</groupId>
             <artifactId>moshi</artifactId>
-            <version>1.14.0</version>
+            <version>1.15.0</version>
         </dependency>
         <dependency>
             <groupId>com.blueconic</groupId>
@@ -280,7 +280,7 @@
         <dependency>
             <groupId>com.github.ben-manes.caffeine</groupId>
             <artifactId>caffeine</artifactId>
-            <version>3.1.5</version>
+            <version>3.1.6</version>
         </dependency>
         <dependency>
             <groupId>com.nulab-inc</groupId>

+ 0 - 1
server/src/main/java/password/pwm/AppProperty.java

@@ -90,7 +90,6 @@ public enum AppProperty
     CLUSTER_LDAP_HEARTBEAT_SECONDS                  ( "cluster.ldap.heartbeatSeconds" ),
     CLUSTER_LDAP_NODE_TIMEOUT_SECONDS               ( "cluster.ldap.nodeTimeoutSeconds" ),
     CLUSTER_LDAP_NODE_PURGE_SECONDS                 ( "cluster.ldap.nodePurgeSeconds" ),
-    DB_JDBC_LOAD_STRATEGY                           ( "db.jdbcLoadStrategy" ),
     DB_CONNECTIONS_MAX                              ( "db.connections.max" ),
     DB_CONNECTIONS_TIMEOUT_MS                       ( "db.connections.timeoutMs" ),
     DB_CONNECTIONS_WATCHDOG_FREQUENCY_SECONDS       ( "db.connections.watchdogFrequencySeconds" ),

+ 14 - 65
server/src/main/java/password/pwm/PwmApplication.java

@@ -20,7 +20,6 @@
 
 package password.pwm;
 
-import lombok.Value;
 import password.pwm.bean.DomainID;
 import password.pwm.bean.ProfileID;
 import password.pwm.bean.SessionLabel;
@@ -28,7 +27,6 @@ import password.pwm.config.AppConfig;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSettingScope;
 import password.pwm.error.ErrorInformation;
-import password.pwm.error.PwmError;
 import password.pwm.error.PwmException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.health.HealthService;
@@ -58,7 +56,7 @@ import password.pwm.svc.wordlist.SharedHistoryService;
 import password.pwm.svc.wordlist.WordlistService;
 import password.pwm.util.MBeanUtility;
 import password.pwm.util.PwmScheduler;
-import password.pwm.util.java.FileSystemUtility;
+import password.pwm.util.java.CollectionUtil;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.json.JsonFactory;
@@ -67,8 +65,6 @@ import password.pwm.util.logging.LocalDBLogger;
 import password.pwm.util.logging.PwmLogManager;
 import password.pwm.util.logging.PwmLogger;
 
-import java.io.IOException;
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.time.Instant;
 import java.util.ArrayList;
@@ -108,6 +104,7 @@ public class PwmApplication
     private String instanceID = PwmApplicationUtil.DEFAULT_INSTANCE_ID;
     private LocalDB localDB;
     private LocalDBLogger localDBLogger;
+    private Path tempDirectory;
 
     public PwmApplication( final PwmEnvironment pwmEnvironment )
             throws PwmUnrecoverableException
@@ -156,22 +153,8 @@ public class PwmApplication
             fileLocker.waitForFileLock();
         }
 
-        // clear temp dir
-        if ( !pwmEnvironment.isInternalRuntimeInstance() )
-        {
-            final Path tempFileDirectory = getTempDirectory();
-            try
-            {
-                LOGGER.debug( sessionLabel, () -> "deleting directory (and sub-directory) contents in " + tempFileDirectory );
-                FileSystemUtility.deleteDirectoryContentsRecursively( tempFileDirectory );
-            }
-            catch ( final Exception e )
-            {
-                throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_STARTUP_ERROR,
-                        "unable to clear temp file directory '" + tempFileDirectory + "', error: " + e.getMessage()
-                ) );
-            }
-        }
+        // init temp dir
+        tempDirectory = PwmApplicationUtil.initTempDirectory( sessionLabel, pwmEnvironment );
 
         if ( getApplicationMode() != PwmApplicationMode.READ_ONLY )
         {
@@ -509,7 +492,7 @@ public class PwmApplication
 
     public Map<ProfileID, ErrorInformation> readLastLdapFailure( final DomainID domainID )
     {
-        return readLastLdapFailure().getRecords().getOrDefault( domainID, Collections.emptyMap() );
+        return readLastLdapFailure().records().getOrDefault( domainID, Collections.emptyMap() );
     }
 
     private StoredErrorRecords readLastLdapFailure()
@@ -534,34 +517,27 @@ public class PwmApplication
         return new StoredErrorRecords( Collections.emptyMap() );
     }
 
-    @Value
-    private static class StoredErrorRecords
+    private record StoredErrorRecords(
+            Map<DomainID, Map<ProfileID, ErrorInformation>> records
+    )
     {
-        private final Map<DomainID, Map<ProfileID, ErrorInformation>> records;
-
-        StoredErrorRecords( final Map<DomainID, Map<ProfileID, ErrorInformation>> records )
-        {
-            this.records = records == null ? Collections.emptyMap() : Map.copyOf( records );
-        }
-
-        public Map<DomainID, Map<ProfileID, ErrorInformation>> getRecords()
+        private StoredErrorRecords( final Map<DomainID, Map<ProfileID, ErrorInformation>> records )
         {
-            // required because json deserialization can still set records == null
-            return records == null ? Collections.emptyMap() : records;
+            this.records = CollectionUtil.stripNulls( records );
         }
 
         StoredErrorRecords addDomainErrorMap(
                 final DomainID domainID,
                 final Map<ProfileID, ErrorInformation> errorInformationMap )
         {
-            final Map<DomainID, Map<ProfileID, ErrorInformation>> newRecords = new HashMap<>( getRecords() );
+            final Map<DomainID, Map<ProfileID, ErrorInformation>> newRecords = new HashMap<>( records );
             newRecords.put( domainID, Map.copyOf( errorInformationMap ) );
             return new StoredErrorRecords( newRecords );
         }
 
         StoredErrorRecords stripOutdatedLdapErrors( final TimeDuration maxAge )
         {
-            return new StoredErrorRecords( getRecords().entrySet().stream()
+            return new StoredErrorRecords( records.entrySet().stream()
                     // outer map
                     .collect( Collectors.toUnmodifiableMap(
                             Map.Entry::getKey,
@@ -787,39 +763,12 @@ public class PwmApplication
         return this.getConfig().isMultiDomain();
     }
 
-    public Path getTempDirectory( )
+    public Optional<Path> getTempDirectory( )
             throws PwmUnrecoverableException
     {
-        if ( pwmEnvironment.getApplicationPath() == null )
-        {
-            final ErrorInformation errorInformation = new ErrorInformation(
-                    PwmError.ERROR_STARTUP_ERROR,
-                    "unable to establish temp work directory: application path unavailable"
-            );
-            throw new PwmUnrecoverableException( errorInformation );
-        }
-        final Path tempDirectory = pwmEnvironment.getApplicationPath().resolve( "temp" );
-        if ( !Files.exists( tempDirectory ) )
-        {
-            LOGGER.trace( () -> "preparing to create temporary directory " + tempDirectory );
-            try
-            {
-                Files.createDirectories( tempDirectory );
-                LOGGER.debug( () -> "created " + tempDirectory );
-            }
-            catch ( final IOException e )
-            {
-                LOGGER.debug( () -> "unable to create temporary directory " + tempDirectory );
-                final ErrorInformation errorInformation = new ErrorInformation(
-                        PwmError.ERROR_STARTUP_ERROR,
-                        "unable to establish create temp work directory " + tempDirectory );
-                throw new PwmUnrecoverableException( errorInformation );
-            }
-        }
-        return tempDirectory;
+        return Optional.ofNullable( tempDirectory );
     }
 
-
     public PwmScheduler getPwmScheduler()
     {
         return pwmScheduler;

+ 53 - 0
server/src/main/java/password/pwm/PwmApplicationUtil.java

@@ -21,6 +21,7 @@
 package password.pwm;
 
 import password.pwm.bean.DomainID;
+import password.pwm.bean.SessionLabel;
 import password.pwm.config.stored.StoredConfigKey;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationUtil;
@@ -45,6 +46,7 @@ import password.pwm.util.secure.PwmRandom;
 import password.pwm.util.secure.X509Utils;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.file.Files;
@@ -354,4 +356,55 @@ class PwmApplicationUtil
     {
         return PwmRandom.getInstance().randomUUID().toString();
     }
+
+    static Path initTempDirectory( final SessionLabel sessionLabel, final PwmEnvironment pwmEnvironment )
+            throws PwmUnrecoverableException
+    {
+        if ( pwmEnvironment.getApplicationPath() == null )
+        {
+            final ErrorInformation errorInformation = new ErrorInformation(
+                    PwmError.ERROR_STARTUP_ERROR,
+                    "unable to establish temp work directory: application path unavailable"
+            );
+            throw new PwmUnrecoverableException( errorInformation );
+        }
+
+        final Path tempDirectory = pwmEnvironment.getApplicationPath().resolve( "temp" );
+
+        if ( !Files.exists( tempDirectory ) )
+        {
+            LOGGER.trace( sessionLabel, () -> "preparing to create temporary directory " + tempDirectory );
+            try
+            {
+                Files.createDirectories( tempDirectory );
+                LOGGER.debug( sessionLabel, () -> "created " + tempDirectory );
+            }
+            catch ( final IOException e )
+            {
+                LOGGER.debug( sessionLabel, () -> "unable to create temporary directory " + tempDirectory );
+                final ErrorInformation errorInformation = new ErrorInformation(
+                        PwmError.ERROR_STARTUP_ERROR,
+                        "unable to establish create temp work directory " + tempDirectory );
+                throw new PwmUnrecoverableException( errorInformation );
+            }
+        }
+
+        // clear temp dir
+        if ( !pwmEnvironment.isInternalRuntimeInstance() )
+        {
+            try
+            {
+                LOGGER.debug( sessionLabel, () -> "deleting directory (and sub-directory) contents in " + tempDirectory );
+                FileSystemUtility.deleteDirectoryContentsRecursively( tempDirectory );
+            }
+            catch ( final Exception e )
+            {
+                throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_STARTUP_ERROR,
+                        "unable to clear temp file directory '" + tempDirectory + "', error: " + e.getMessage()
+                ) );
+            }
+        }
+
+        return tempDirectory;
+    }
 }

+ 5 - 0
server/src/main/java/password/pwm/http/ContextManager.java

@@ -257,6 +257,11 @@ public class ContextManager
             handleStartupError( "unable to initialize application: ", e );
         }
 
+        if ( taskMaster != null )
+        {
+            taskMaster.shutdownNow();
+        }
+
         taskMaster = Executors.newSingleThreadScheduledExecutor(
                 PwmScheduler.makePwmThreadFactory(
                         PwmScheduler.makeThreadName( SESSION_LABEL, pwmApplication, this.getClass() ) + "-"

+ 2 - 2
server/src/main/java/password/pwm/http/servlet/configeditor/ConfigEditorServlet.java

@@ -672,7 +672,7 @@ public class ConfigEditorServlet extends ControlledPwmServlet
             final Optional<EmailServer> emailServer = EmailServerUtil.makeEmailServer( testDomainConfig, emailServerProfile, null );
             if ( emailServer.isPresent() )
             {
-                final MacroRequest macroRequest = SampleDataGenerator.sampleMacroRequest( pwmRequest.getPwmDomain() );
+                final MacroRequest macroRequest = SampleDataGenerator.sampleMacroRequest( pwmRequest.getPwmApplication().getTempDirectory().orElseThrow() );
 
                 try
                 {
@@ -800,7 +800,7 @@ public class ConfigEditorServlet extends ControlledPwmServlet
                 return ProcessStatus.Halt;
             }
 
-            final MacroRequest macroRequest = SampleDataGenerator.sampleMacroRequest( pwmRequest.getPwmDomain() );
+            final MacroRequest macroRequest = SampleDataGenerator.sampleMacroRequest( pwmRequest.getPwmApplication().getTempDirectory().orElseThrow() );
             final String input = inputMap.get( "input" );
             final String output = macroRequest.expandMacros( input );
             pwmRequest.outputJsonResult( RestResultBean.withData( output, String.class ) );

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/setupresponses/SetupResponsesServlet.java

@@ -301,7 +301,7 @@ public class SetupResponsesServlet extends ControlledPwmServlet
 
             final Instant startMakeResponseSet = Instant.now();
             SetupResponsesUtil.generateResponseInfoBean( pwmRequest, challengeSet, responseMap, Collections.emptyMap() );
-            LOGGER.error( pwmRequest, () -> "generated hashed response set in "
+            LOGGER.trace( pwmRequest, () -> "generated hashed response set in "
                     + TimeDuration.fromCurrent( startMakeResponseSet ).asCompactString() );
             success = true;
         }

+ 2 - 2
server/src/main/java/password/pwm/svc/AbstractPwmService.java

@@ -174,7 +174,7 @@ public abstract class AbstractPwmService implements PwmService
 
     protected void scheduleFixedRateJob( final Runnable runnable, final TimeDuration initialDelay, final TimeDuration repeatInterval )
     {
-        pwmApplication.getPwmScheduler().scheduleFixedRateJob( new WrappedRunnable( runnable ),
+        PwmScheduler.scheduleFixedRateJob( new WrappedRunnable( runnable ),
                 executorService.get(),
                 initialDelay,
                 repeatInterval );
@@ -194,7 +194,7 @@ public abstract class AbstractPwmService implements PwmService
 
     protected void scheduleDailyZuluZeroStartJob( final Runnable runnable, final TimeDuration zuluOffset )
     {
-        pwmApplication.getPwmScheduler().scheduleDailyZuluZeroStartJob( new WrappedRunnable( runnable ),
+        PwmScheduler.scheduleDailyZuluZeroStartJob( new WrappedRunnable( runnable ),
                 executorService.get(),
                 zuluOffset );
     }

+ 0 - 11
server/src/main/java/password/pwm/svc/db/DBConfiguration.java

@@ -29,11 +29,8 @@ import password.pwm.config.PwmSetting;
 import password.pwm.config.value.FileValue;
 import password.pwm.data.ImmutableByteArray;
 import password.pwm.util.PasswordData;
-import password.pwm.util.java.CollectionUtil;
 
-import java.util.Arrays;
 import java.util.Map;
-import java.util.Set;
 
 @Value
 @AllArgsConstructor( access = AccessLevel.PRIVATE )
@@ -46,7 +43,6 @@ public class DBConfiguration
     private final String columnTypeKey;
     private final String columnTypeValue;
     private final ImmutableByteArray jdbcDriver;
-    private final Set<JDBCDriverLoader.ClassLoaderStrategy> classLoaderStrategies;
     private final int maxConnections;
     private final int connectionTimeout;
     private final int keyColumnLength;
@@ -72,12 +68,6 @@ public class DBConfiguration
             jdbcDriverBytes = null;
         }
 
-        final String strategyList = config.readAppProperty( AppProperty.DB_JDBC_LOAD_STRATEGY );
-        final Set<JDBCDriverLoader.ClassLoaderStrategy> strategies = CollectionUtil.readEnumSetFromStringCollection(
-                JDBCDriverLoader.ClassLoaderStrategy.class,
-                Arrays.asList( strategyList.split( "," ) )
-        );
-
         final int maxConnections = Integer.parseInt( config.readAppProperty( AppProperty.DB_CONNECTIONS_MAX ) );
         final int connectionTimeout = Integer.parseInt( config.readAppProperty( AppProperty.DB_CONNECTIONS_TIMEOUT_MS ) );
 
@@ -93,7 +83,6 @@ public class DBConfiguration
                 config.readSettingAsString( PwmSetting.DATABASE_COLUMN_TYPE_KEY ),
                 config.readSettingAsString( PwmSetting.DATABASE_COLUMN_TYPE_VALUE ),
                 jdbcDriverBytes,
-                strategies,
                 maxConnections,
                 connectionTimeout,
                 keyColumnLength,

+ 1 - 1
server/src/main/java/password/pwm/svc/db/DatabaseAccessorImpl.java

@@ -340,7 +340,7 @@ class DatabaseAccessorImpl implements DatabaseAccessor
         private PreparedStatement statement;
         private Map.Entry<String, String> nextValue;
         private boolean finished;
-        private int counter = ITERATOR_COUNTER.getAndIncrement();
+        private final int counter = ITERATOR_COUNTER.getAndIncrement();
 
         DBIterator( final DatabaseTable table )
                 throws DatabaseException

+ 3 - 24
server/src/main/java/password/pwm/svc/db/DatabaseService.java

@@ -45,7 +45,7 @@ import password.pwm.util.logging.PwmLogger;
 
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
-import java.sql.Driver;
+import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.time.Instant;
 import java.util.ArrayList;
@@ -70,9 +70,6 @@ public class DatabaseService extends AbstractPwmService implements PwmService
 
     private DBConfiguration dbConfiguration;
 
-    private Driver driver;
-    private JDBCDriverLoader.DriverLoader jdbcDriverLoader;
-
     private ErrorInformation lastError;
 
     private AtomicLoopIntIncrementer slotIncrementer;
@@ -199,21 +196,6 @@ public class DatabaseService extends AbstractPwmService implements PwmService
         setStatus( STATUS.CLOSED );
 
         clearCurrentAccessors();
-
-        try
-        {
-            driver = null;
-        }
-        catch ( final Exception e )
-        {
-            LOGGER.debug( getSessionLabel(), () -> "error while de-registering driver: " + e.getMessage() );
-        }
-
-        if ( jdbcDriverLoader != null )
-        {
-            jdbcDriverLoader.unloadDriver();
-            jdbcDriverLoader = null;
-        }
     }
 
     private void clearCurrentAccessors( )
@@ -358,13 +340,10 @@ public class DatabaseService extends AbstractPwmService implements PwmService
     {
         final String connectionURL = dbConfiguration.getConnectionString();
 
-        final JDBCDriverLoader.DriverWrapper wrapper = JDBCDriverLoader.loadDriver( getPwmApplication(), dbConfiguration );
-        driver = wrapper.getDriver();
-        jdbcDriverLoader = wrapper.getDriverLoader();
-
         try
         {
             LOGGER.debug( getSessionLabel(), () -> "initiating connecting to database " + connectionURL );
+            JDBCDriverLoader.loadDriver( getPwmApplication(), dbConfiguration );
             final Properties connectionProperties = new Properties();
             if ( dbConfiguration.getUsername() != null && !dbConfiguration.getUsername().isEmpty() )
             {
@@ -375,7 +354,7 @@ public class DatabaseService extends AbstractPwmService implements PwmService
                 connectionProperties.setProperty( "password", dbConfiguration.getPassword().getStringValue() );
             }
 
-            final Connection connection = driver.connect( connectionURL, connectionProperties );
+            final Connection connection = DriverManager.getConnection( connectionURL, connectionProperties );
             LOGGER.debug( getSessionLabel(), () -> "connected to database " + connectionURL );
 
             connection.setAutoCommit( false );

+ 98 - 234
server/src/main/java/password/pwm/svc/db/JDBCDriverLoader.java

@@ -21,47 +21,46 @@
 package password.pwm.svc.db;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import org.xeustechnologies.jcl.JarClassLoader;
-import org.xeustechnologies.jcl.JclObjectFactory;
 import password.pwm.PwmApplication;
-import password.pwm.PwmConstants;
 import password.pwm.data.ImmutableByteArray;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmUnrecoverableException;
-import password.pwm.util.java.JavaHelper;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.util.logging.PwmLogger;
 
 import java.io.IOException;
-import java.io.OutputStream;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import java.sql.Connection;
 import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Logger;
 
 public class JDBCDriverLoader
 {
 
     private static final PwmLogger LOGGER = PwmLogger.forClass( JDBCDriverLoader.class, true );
 
-    static DriverWrapper loadDriver(
+    static Driver loadDriver(
             final PwmApplication pwmApplication,
             final DBConfiguration dbConfiguration
     )
             throws DatabaseException
     {
-        final Set<ClassLoaderStrategy> strategies = dbConfiguration.getClassLoaderStrategies();
+        final Set<ClassLoaderStrategy> strategies = Set.of( ClassLoaderStrategy.AppPathFileLoader, ClassLoaderStrategy.Classpath );
         LOGGER.trace( () -> "attempting to load jdbc driver using strategies: " + JsonFactory.get().serializeCollection( strategies ) );
         final List<String> errorMsgs = new ArrayList<>();
         for ( final ClassLoaderStrategy strategy : strategies )
@@ -72,7 +71,7 @@ public class JDBCDriverLoader
                 final Driver driver = loader.loadDriver( pwmApplication, dbConfiguration );
                 if ( driver != null )
                 {
-                    return new DriverWrapper( driver, loader );
+                    return driver;
                 }
             }
             catch ( final PwmUnrecoverableException | DatabaseException e )
@@ -88,9 +87,7 @@ public class JDBCDriverLoader
 
     public enum ClassLoaderStrategy
     {
-        XeusLoader( XeusJarClassDriverLoader.class ),
         AppPathFileLoader( AppPathDriverLoader.class ),
-        TempFile( TempFileDriverLoader.class ),
         Classpath( JavaClasspathLoader.class ),;
 
         private final Class<? extends DriverLoader> jdbcDriverDriverLoaderClass;
@@ -119,14 +116,12 @@ public class JDBCDriverLoader
     interface DriverLoader
     {
         Driver loadDriver( PwmApplication pwmApplication, DBConfiguration dbConfiguration ) throws DatabaseException;
-
-        void unloadDriver( );
     }
 
     private static class JavaClasspathLoader implements DriverLoader
     {
 
-        private static final PwmLogger LOGGER = PwmLogger.forClass( XeusJarClassDriverLoader.class, true );
+        private static final PwmLogger LOGGER = PwmLogger.forClass( JavaClasspathLoader.class, true );
 
         @Override
         public Driver loadDriver( final PwmApplication pwmApplication, final DBConfiguration dbConfiguration )
@@ -137,7 +132,7 @@ public class JDBCDriverLoader
             try
             {
                 LOGGER.debug( () -> "loading JDBC database driver from classpath: " + jdbcClassName );
-                final Driver driver = ( Driver ) Class.forName( jdbcClassName ).getDeclaredConstructor().newInstance();
+                final Driver driver = DriverManager.getDriver( dbConfiguration.getConnectionString() );
 
                 LOGGER.debug( () -> "successfully loaded JDBC database driver from classpath: " + jdbcClassName );
                 return driver;
@@ -149,74 +144,16 @@ public class JDBCDriverLoader
                 throw new DatabaseException( errorInformation );
             }
         }
-
-        @Override
-        public void unloadDriver( )
-        {
-        }
     }
 
 
-    private static class XeusJarClassDriverLoader implements DriverLoader
-    {
-
-        private static final PwmLogger LOGGER = PwmLogger.forClass( XeusJarClassDriverLoader.class, true );
-
-
-        @Override
-        public Driver loadDriver( final PwmApplication pwmApplication, final DBConfiguration dbConfiguration )
-                throws DatabaseException
-        {
-            final String jdbcClassName = dbConfiguration.getDriverClassname();
-            final ImmutableByteArray jdbcDriverBytes = dbConfiguration.getJdbcDriver();
-            try
-            {
-                LOGGER.debug( () -> "loading JDBC database driver stored in configuration" );
-
-                final JarClassLoader jarClassLoader = AccessController.doPrivileged(
-                        ( PrivilegedAction<JarClassLoader> ) JarClassLoader::new
-                );
-
-                jarClassLoader.add( jdbcDriverBytes.newByteArrayInputStream() );
-                final JclObjectFactory jclObjectFactory = JclObjectFactory.getInstance( true );
-
-                //Create object of loaded class
-                final Driver driver = ( Driver ) jclObjectFactory.create( jarClassLoader, jdbcClassName );
-
-                LOGGER.debug( () -> "successfully loaded JDBC database driver '" + jdbcClassName + "' from application configuration" );
-
-                return driver;
-            }
-            catch ( final Throwable e )
-            {
-                final String errorMsg = "error registering JDBC database driver stored in configuration: " + e.getMessage();
-                final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_DB_UNAVAILABLE, errorMsg );
-                throw new DatabaseException( errorInformation );
-            }
-        }
-
-        @Override
-        public void unloadDriver( )
-        {
-
-        }
-    }
-
-    private static class TempFileDriverLoader implements DriverLoader
+    private static class AppPathDriverLoader implements DriverLoader
     {
+        private static final PwmLogger LOGGER = PwmLogger.forClass( AppPathDriverLoader.class, true );
 
-        private static final PwmLogger LOGGER = PwmLogger.forClass( TempFileDriverLoader.class, true );
-
-        private Path tempFile;
-
-        @Override
-
-        // not clear if this is worth it to fix
-        @SuppressFBWarnings( "DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED" )
         public Driver loadDriver( final PwmApplication pwmApplication, final DBConfiguration dbConfiguration )
                 throws DatabaseException
         {
-            final String jdbcClassName = dbConfiguration.getDriverClassname();
             final ImmutableByteArray jdbcDriverBytes = dbConfiguration.getJdbcDriver();
 
             if ( jdbcDriverBytes == null || jdbcDriverBytes.size() < 1 )
@@ -225,139 +162,24 @@ public class JDBCDriverLoader
                 final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_DB_UNAVAILABLE, errorMsg );
                 throw new DatabaseException( errorInformation );
             }
+
             try
             {
-                LOGGER.debug( () -> "loading JDBC database driver stored in configuration" );
-
-                if ( tempFile == null )
+                if ( !createAndRegisterDriverJar( pwmApplication, dbConfiguration ) )
                 {
-                    final String prefixName = PwmConstants.PWM_APP_NAME.toLowerCase() + "_jdbcJar_";
-                    tempFile = Files.createTempFile( pwmApplication.getTempDirectory(), prefixName, "jar" );
-                    LOGGER.trace( () -> "created temp file " + tempFile );
+                    return null;
                 }
-
-                try ( OutputStream outputStream = Files.newOutputStream( tempFile ) )
-                {
-                    JavaHelper.copy( jdbcDriverBytes.newByteArrayInputStream(), outputStream );
-                }
-
-                final URLClassLoader urlClassLoader = new URLClassLoader(
-                        new URL[]
-                                {
-                                        tempFile.toUri().toURL(),
-                                },
-                        this.getClass().getClassLoader()
-                );
-
-                //Create object of loaded class
-                final Class<?> jdbcDriverClass = urlClassLoader.loadClass( jdbcClassName );
-                final Driver driver = ( Driver ) jdbcDriverClass.getDeclaredConstructor().newInstance();
-
-                LOGGER.debug( () -> "successfully loaded JDBC database driver '" + jdbcClassName + "' from application configuration" );
-
-                return driver;
             }
             catch ( final Throwable e )
             {
-                final String errorMsg = "error registering JDBC database driver stored in configuration: " + e.getMessage();
-                final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_DB_UNAVAILABLE, errorMsg );
-                throw new DatabaseException( errorInformation );
-            }
-        }
-
-        @Override
-        public void unloadDriver( )
-        {
-            if ( tempFile != null )
-            {
-                try
-                {
-                    if ( Files.deleteIfExists( tempFile ) )
-                    {
-                        LOGGER.trace( () -> "removed temporary file " + tempFile );
-                    }
-                }
-                catch ( final IOException e )
-                {
-                    LOGGER.trace( () -> "error removing temporary file " + tempFile + ", error: " + e.getMessage(), e );
-                }
-            }
-            tempFile = null;
-        }
-    }
-
-    private static class AppPathDriverLoader implements DriverLoader
-    {
-
-        private static final PwmLogger LOGGER = PwmLogger.forClass( AppPathDriverLoader.class, true );
-
-        // static cache of classloader to prevent classloader memory leak
-        private static Map<String, ClassLoader> driverCache = new ConcurrentHashMap<>();
-
-
-        @Override
-
-        // not clear if this is worth it to fix
-        @SuppressFBWarnings( "DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED" )
-        public Driver loadDriver( final PwmApplication pwmApplication, final DBConfiguration dbConfiguration )
-                throws DatabaseException
-        {
-            final String jdbcClassName = dbConfiguration.getDriverClassname();
-            final ImmutableByteArray jdbcDriverBytes = dbConfiguration.getJdbcDriver();
-
-            if ( jdbcDriverBytes == null || jdbcDriverBytes.size() < 1 )
-            {
-                final String errorMsg = "jdbc driver file not configured, skipping";
+                final String errorMsg = "error establishing classloader for driver: " + e.getMessage();
                 final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_DB_UNAVAILABLE, errorMsg );
                 throw new DatabaseException( errorInformation );
             }
 
-            final String jdbcDriverHash;
             try
             {
-                jdbcDriverHash = pwmApplication.getSecureService().hash( jdbcDriverBytes.newByteArrayInputStream() );
-            }
-            catch ( final PwmUnrecoverableException e )
-            {
-                throw new DatabaseException( e.getErrorInformation() );
-            }
-
-            final ClassLoader urlClassLoader;
-            if ( driverCache.containsKey( jdbcDriverHash ) )
-            {
-                urlClassLoader = driverCache.get( jdbcDriverHash );
-                LOGGER.trace( () -> "loaded classloader from static cache" );
-            }
-            else
-            {
-                try
-                {
-                    LOGGER.debug( () -> "loading JDBC database driver stored in configuration" );
-                    final Path tempFile = createOrGetTempJarFile( pwmApplication, jdbcDriverBytes );
-                    urlClassLoader = new URLClassLoader(
-                            new URL[]
-                                    {
-                                            tempFile.toUri().toURL(),
-                                    },
-                            this.getClass().getClassLoader()
-                    );
-                    driverCache.put( jdbcDriverHash, urlClassLoader );
-                }
-                catch ( final Throwable e )
-                {
-                    final String errorMsg = "error establishing classloader for driver: " + e.getMessage();
-                    final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_DB_UNAVAILABLE, errorMsg );
-                    throw new DatabaseException( errorInformation );
-                }
-            }
-
-            try
-            {
-                //Create object of loaded class
-                final Class<?> jdbcDriverClass = urlClassLoader.loadClass( jdbcClassName );
-                final Driver driver = ( Driver ) jdbcDriverClass.getDeclaredConstructor().newInstance();
-                LOGGER.debug( () -> "successfully loaded JDBC database driver '" + jdbcClassName + "' from application configuration" );
-                return driver;
+                return DriverManager.getDriver( dbConfiguration.getConnectionString() );
             }
             catch ( final Throwable e )
             {
@@ -367,63 +189,105 @@ public class JDBCDriverLoader
             }
         }
 
-        @Override
-        public void unloadDriver( )
+        @SuppressFBWarnings( "DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED" )
+        boolean createAndRegisterDriverJar(
+                final PwmApplication pwmApplication,
+                final DBConfiguration dbConfiguration
+        )
+                throws PwmUnrecoverableException, IOException, ClassNotFoundException, NoSuchMethodException,
+                InvocationTargetException, InstantiationException, IllegalAccessException, SQLException
         {
-        }
+            final Optional<Path> pwmTempDir = pwmApplication.getTempDirectory();
+            if ( pwmTempDir.isEmpty() )
+            {
+                return false;
+            }
 
-        Path createOrGetTempJarFile( final PwmApplication pwmApplication, final ImmutableByteArray jarBytes )
-                throws PwmUnrecoverableException, IOException
-        {
-            final Path file = pwmApplication.getTempDirectory();
-            final String jarHash = pwmApplication.getSecureService().hash( jarBytes.newByteArrayInputStream() );
+            final byte[] jarBytes = dbConfiguration.getJdbcDriver().copyOf();
+            final String jarHash = pwmApplication.getSecureService().hash( jarBytes );
             final String tempFileName = "jar-" + jarHash + ".jar";
-            final Path tempFile = file.resolve( tempFileName );
+            final Path tempFile = pwmTempDir.get().resolve( tempFileName );
+
             if ( Files.exists( tempFile ) )
             {
-                final String fileHash = pwmApplication.getSecureService().hash( tempFile );
-                if ( !jarHash.equals( fileHash ) )
-                {
-                    LOGGER.debug( () -> "existing temp jar file " + tempFile + " has wrong contents, will delete" );
-                    Files.delete( tempFile );
-                }
-            }
-            if ( !Files.exists( tempFile ) )
-            {
-                LOGGER.debug( () -> "creating temp jar file " + tempFile );
-                try ( OutputStream fos = Files.newOutputStream( tempFile ) )
-                {
-                    JavaHelper.copy( jarBytes.newByteArrayInputStream(), fos );
-                }
-            }
-            else
-            {
-                LOGGER.trace( () -> "reusing existing temp jar file " + tempFile );
+                LOGGER.trace( () -> "reusing existing temp jar file and registration: " + tempFile );
+                return true;
             }
 
-            return tempFile;
+            LOGGER.debug( () -> "creating temp jar file " + tempFile );
+            Files.write( tempFile, jarBytes );
+
+            // load into classloader
+            final URLClassLoader urlClassLoader = new URLClassLoader(
+                    new URL[]
+                            {
+                                    tempFile.toUri().toURL(),
+                            },
+                    this.getClass().getClassLoader() );
+
+            //Create object of loaded class
+            final Class<?> jdbcDriverClass = urlClassLoader.loadClass( dbConfiguration.getDriverClassname() );
+            final Driver driver = new DriverShim( ( Driver ) jdbcDriverClass.getDeclaredConstructor().newInstance() );
+            LOGGER.debug( () -> "successfully loaded JDBC database driver '" + dbConfiguration.getDriverClassname() + "' from application configuration" );
+            DriverManager.registerDriver( driver );
+            return true;
+
         }
     }
 
-    static class DriverWrapper
+    private static class DriverShim implements Driver
     {
         private final Driver driver;
-        private final DriverLoader driverLoader;
 
-        DriverWrapper( final Driver driver, final DriverLoader driverLoader )
+        DriverShim( final Driver driver )
         {
             this.driver = driver;
-            this.driverLoader = driverLoader;
         }
 
-        public Driver getDriver( )
+        @Override
+        public Connection connect( final String url, final Properties info )
+                throws SQLException
         {
-            return driver;
+            return driver.connect( url, info );
         }
 
-        public DriverLoader getDriverLoader( )
+        @Override
+        public boolean acceptsURL( final String url )
+                throws SQLException
+        {
+            return driver.acceptsURL( url );
+        }
+
+        @Override
+        public DriverPropertyInfo[] getPropertyInfo( final String url, final Properties info )
+                throws SQLException
+        {
+            return driver.getPropertyInfo( url, info );
+        }
+
+        @Override
+        public int getMajorVersion()
+        {
+            return driver.getMajorVersion();
+        }
+
+        @Override
+        public int getMinorVersion()
+        {
+            return driver.getMinorVersion();
+        }
+
+        @Override
+        public boolean jdbcCompliant()
+        {
+            return driver.jdbcCompliant();
+        }
+
+        @Override
+        public Logger getParentLogger()
+                throws SQLFeatureNotSupportedException
         {
-            return driverLoader;
+            return driver.getParentLogger();
         }
     }
 }

+ 1 - 1
server/src/main/java/password/pwm/svc/event/LocalDbAuditVault.java

@@ -74,7 +74,7 @@ public class LocalDbAuditVault implements AuditVault
 
         status = PwmService.STATUS.OPEN;
         final TimeDuration jobFrequency = TimeDuration.of( 10, TimeDuration.Unit.MINUTES );
-        pwmApplication.getPwmScheduler().scheduleFixedRateJob( new TrimmerThread(), executorService, TimeDuration.SECONDS_10, jobFrequency );
+        PwmScheduler.scheduleFixedRateJob( new TrimmerThread(), executorService, TimeDuration.SECONDS_10, jobFrequency );
     }
 
     @Override

+ 10 - 4
server/src/main/java/password/pwm/svc/userhistory/DatabaseUserHistory.java

@@ -31,6 +31,7 @@ import password.pwm.svc.db.DatabaseException;
 import password.pwm.svc.db.DatabaseService;
 import password.pwm.svc.db.DatabaseTable;
 import password.pwm.svc.event.AuditEventType;
+import password.pwm.svc.event.AuditRecordData;
 import password.pwm.svc.event.HelpdeskAuditRecord;
 import password.pwm.svc.event.UserAuditRecord;
 import password.pwm.user.UserInfo;
@@ -38,8 +39,10 @@ import password.pwm.util.java.CollectionUtil;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.util.logging.PwmLogger;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 class DatabaseUserHistory implements UserHistoryStore
 {
@@ -78,8 +81,9 @@ class DatabaseUserHistory implements UserHistoryStore
         {
             final StoredHistory storedHistory;
             storedHistory = readStoredHistory( guid );
-            storedHistory.records().add( auditRecord );
-            writeStoredHistory( guid, storedHistory );
+            final List<AuditRecordData> mutableRecordList = new ArrayList<>( storedHistory.records() );
+            mutableRecordList.add( ( AuditRecordData ) auditRecord );
+            writeStoredHistory( guid, new StoredHistory( mutableRecordList ) );
         }
         catch ( final DatabaseException e )
         {
@@ -93,7 +97,9 @@ class DatabaseUserHistory implements UserHistoryStore
         final String userGuid = userInfo.getUserGuid();
         try
         {
-            return readStoredHistory( userGuid ).records();
+            return readStoredHistory( userGuid ).records().stream()
+                    .map( auditRecordData -> ( UserAuditRecord ) auditRecordData )
+                    .collect( Collectors.toList() );
         }
         catch ( final DatabaseException e )
         {
@@ -122,7 +128,7 @@ class DatabaseUserHistory implements UserHistoryStore
     }
 
     record StoredHistory(
-            List<UserAuditRecord> records
+            List<AuditRecordData> records
     )
     {
         StoredHistory

+ 8 - 7
server/src/main/java/password/pwm/svc/userhistory/LdapXmlUserHistory.java

@@ -222,10 +222,12 @@ public class LdapXmlUserHistory implements UserHistoryStore
                 return StoredHistory.fromXml( theCor.getPayload() );
             }
         }
-        catch ( final ChaiOperationException e )
+        catch ( final Exception e )
         {
-            LOGGER.error( sessionLabel, () -> "ldap error reading user event log: " + e.getMessage() );
+            LOGGER.error( sessionLabel, () -> "error reading user history for "
+                    + userIdentity.toString() + ", error: " + e.getMessage() );
         }
+
         return new StoredHistory();
     }
 
@@ -295,7 +297,10 @@ public class LdapXmlUserHistory implements UserHistoryStore
             }
         }
 
-        public static StoredHistory fromXml( final String input )
+        public static StoredHistory fromXml(
+                final String input
+        )
+                throws IOException
         {
             final StoredHistory returnHistory = new StoredHistory();
 
@@ -328,10 +333,6 @@ public class LdapXmlUserHistory implements UserHistoryStore
                     } ) );
                 }
             }
-            catch ( final IOException e )
-            {
-                LOGGER.error( () -> "error parsing user event history record: " + e.getMessage() );
-            }
             return returnHistory;
         }
     }

+ 1 - 1
server/src/main/java/password/pwm/svc/wordlist/AbstractWordlist.java

@@ -124,7 +124,7 @@ abstract class AbstractWordlist extends AbstractPwmService implements Wordlist,
 
         if ( !pwmApplication.getPwmEnvironment().isInternalRuntimeInstance() )
         {
-            pwmApplication.getPwmScheduler().scheduleFixedRateJob(
+            PwmScheduler.scheduleFixedRateJob(
                     new InspectorJob(), executorService, TimeDuration.SECOND, wordlistConfiguration.getInspectorFrequency() );
         }
 

+ 4 - 7
server/src/main/java/password/pwm/util/PwmScheduler.java

@@ -51,9 +51,8 @@ import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.stream.Collectors;
 
-public class PwmScheduler
+public final class PwmScheduler
 {
     private static final PwmLogger LOGGER = PwmLogger.forClass( PwmScheduler.class );
 
@@ -83,7 +82,7 @@ public class PwmScheduler
         executor.submit( runnable );
     }
 
-    public void scheduleDailyZuluZeroStartJob(
+    public static void scheduleDailyZuluZeroStartJob(
             final Runnable runnable,
             final ScheduledExecutorService executorService,
             final TimeDuration zuluOffset
@@ -123,7 +122,7 @@ public class PwmScheduler
 
         final List<Future<T>> futures = callables.stream()
                 .map( executor::submit )
-                .collect( Collectors.toUnmodifiableList() );
+                .toList();
 
 
         final List<T> results = new ArrayList<>();
@@ -162,15 +161,13 @@ public class PwmScheduler
     }
 
 
-    public void scheduleFixedRateJob(
+    public static void scheduleFixedRateJob(
             final Runnable runnable,
             final ScheduledExecutorService executor,
             final TimeDuration initialDelay,
             final TimeDuration frequency
     )
     {
-        checkIfSchedulerClosed();
-
         executor.scheduleAtFixedRate( runnable, initialDelay.asMillis(), frequency.asMillis(), TimeUnit.MILLISECONDS );
     }
 

+ 7 - 7
server/src/main/java/password/pwm/util/SampleDataGenerator.java

@@ -24,7 +24,6 @@ import com.novell.ldapchai.cr.Answer;
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplicationMode;
 import password.pwm.PwmConstants;
-import password.pwm.PwmDomain;
 import password.pwm.PwmEnvironment;
 import password.pwm.bean.DomainID;
 import password.pwm.bean.LoginInfoBean;
@@ -47,6 +46,7 @@ import password.pwm.user.UserInfoBean;
 import password.pwm.util.logging.PwmLogLevel;
 import password.pwm.util.macro.MacroRequest;
 
+import java.nio.file.Path;
 import java.time.Instant;
 import java.util.Collections;
 import java.util.Map;
@@ -158,7 +158,7 @@ public class SampleDataGenerator
                 .build();
     }
 
-    public static MacroRequest sampleMacroRequest( final PwmDomain pwmDomain )
+    public static MacroRequest sampleMacroRequest( final Path applicationPath )
             throws PwmUnrecoverableException
     {
         final UserInfo targetUserInfoBean = sampleTargetUserInfo();
@@ -172,7 +172,7 @@ public class SampleDataGenerator
         loginInfoBean.setUserCurrentPassword( PasswordData.forStringValue( "PaSSw0rd" ) );
 
         return MacroRequest.builder()
-                .pwmApplication( makeSamplePwmApp( ) )
+                .pwmApplication( makeSamplePwmApp( applicationPath ) )
                 .userInfo( userInfoBean )
                 .targetUserInfo( targetUserInfoBean )
                 .loginInfoBean( loginInfoBean )
@@ -196,18 +196,18 @@ public class SampleDataGenerator
         return AppConfig.forStoredConfig( modifier.newStoredConfiguration() );
     }
 
-    private static PwmApplication makeSamplePwmApp()
+    private static PwmApplication makeSamplePwmApp( final Path applicationPath )
             throws PwmUnrecoverableException
     {
-        return makeSamplePwmApp( makeConfig() );
+        return makeSamplePwmApp( makeConfig(), applicationPath );
     }
 
-    private static PwmApplication makeSamplePwmApp( final AppConfig appConfig )
+    private static PwmApplication makeSamplePwmApp( final AppConfig appConfig, final Path applicationPath )
             throws PwmUnrecoverableException
     {
         final PwmEnvironment pwmEnvironment = PwmEnvironment.builder()
                 .config( appConfig )
-                .applicationPath( null )
+                .applicationPath( applicationPath )
                 .applicationMode( PwmApplicationMode.READ_ONLY )
                 .internalRuntimeInstance( true )
                 .build();

+ 0 - 1
server/src/main/resources/password/pwm/AppProperty.properties

@@ -78,7 +78,6 @@ configEditor.settingFunction.timeoutMs=5000
 configGuide.idleTimeoutSeconds=3600
 configManager.zipDebug.maxLogBytes=50000000
 configManager.zipDebug.maxLogSeconds=120
-db.jdbcLoadStrategy=AppPathFileLoader,Classpath
 db.connections.max=5
 db.connections.timeoutMs=30000
 db.connections.watchdogFrequencySeconds=30

+ 2 - 1
server/src/test/java/password/pwm/svc/event/LdapXmlUserHistoryTest.java

@@ -54,7 +54,8 @@ public class LdapXmlUserHistoryTest
         final PwmDomain pwmDomain = pwmApplication.domains().get( DomainID.DOMAIN_ID_DEFAULT );
         final ResourceBundle bundle = ResourceBundle.getBundle( LdapXmlUserHistoryTest.class.getName() );
         final String xmlValue1 =  bundle.getString( "xmlValue1" );
-        final LdapXmlUserHistory.StoredHistory storedHistory = LdapXmlUserHistory.StoredHistory.fromXml( xmlValue1 );
+        final LdapXmlUserHistory.StoredHistory storedHistory = LdapXmlUserHistory.StoredHistory
+                .fromXml( xmlValue1 );
 
         final List<UserAuditRecord> auditEventList = storedHistory.asAuditRecords(
                 AuditRecordFactory.make( SessionLabel.TEST_SESSION_LABEL,  pwmDomain ), SampleDataGenerator.sampleUserData() );

+ 6 - 1
server/src/test/java/password/pwm/util/macro/MacroTest.java

@@ -23,23 +23,28 @@ package password.pwm.util.macro;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
 import password.pwm.PwmConstants;
 import password.pwm.config.PwmSetting;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.SampleDataGenerator;
 
+import java.nio.file.Path;
 import java.time.Duration;
 import java.time.Instant;
 import java.util.concurrent.TimeUnit;
 
 public class MacroTest
 {
+    @TempDir
+    public Path temporaryFolder;
+
     private MacroRequest macroRequest;
 
     @BeforeEach
     public void setUp() throws PwmUnrecoverableException
     {
-        macroRequest = SampleDataGenerator.sampleMacroRequest( null );
+        macroRequest = SampleDataGenerator.sampleMacroRequest( temporaryFolder );
     }
 
 

+ 0 - 10
webapp/pom.xml

@@ -262,16 +262,6 @@
             <artifactId>pwm-client</artifactId>
             <version>${project.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.webjars.npm</groupId>
-            <artifactId>tinymce</artifactId>
-            <version>6.3.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.webjars.npm</groupId>
-            <artifactId>jodit</artifactId>
-            <version>3.24.2</version>
-        </dependency>
         <dependency>
             <groupId>org.webjars.npm</groupId>
             <artifactId>dojo</artifactId>

+ 0 - 17
webapp/src/main/webapp/WEB-INF/jsp/admin-dashboard.jsp

@@ -229,23 +229,6 @@
                                 <% } %>
                             </td>
                         </tr>
-                        <tr>
-                            <td class="key">
-                                Dojo API Version
-                            </td>
-                            <td>
-                                <span id="dojoVersionSpan"></span>
-                                <pwm:script>
-                                    <script type="text/javascript">
-                                        PWM_GLOBAL['startupFunctions'].push(function(){
-                                            require(["dojo"],function(dojo){
-                                                dojo.byId('dojoVersionSpan').innerHTML = dojo.version;
-                                            });
-                                        });
-                                    </script>
-                                </pwm:script>
-                            </td>
-                        </tr>
                         <tr>
                             <td class="key">
                                 License Information

+ 1 - 1
webapp/src/main/webapp/public/resources/js/main.js

@@ -190,7 +190,7 @@ PWM_MAIN.initPage = function() {
             try {
                 startupFunction();
             } catch(e) {
-                console.error('error executing startup function: ' + e);
+                console.error('error executing startup function: ' + e,e);
             }
         })
     });