소스 검색

update dependencies, fix issues found in spotbugs 4.7.0

Jason Rivard 3 년 전
부모
커밋
d9175fc1f4
93개의 변경된 파일542개의 추가작업 그리고 301개의 파일을 삭제
  1. 13 2
      build/spotbugs-exclude.xml
  2. 1 1
      data-service/pom.xml
  3. 5 0
      lib-util/src/main/java/password/pwm/util/java/LazySupplier.java
  4. 4 8
      lib-util/src/main/java/password/pwm/util/java/StringUtil.java
  5. 1 1
      onejar/pom.xml
  6. 2 2
      pom.xml
  7. 1 1
      server/pom.xml
  8. 0 1
      server/src/main/java/password/pwm/PwmDomainUtil.java
  9. 4 2
      server/src/main/java/password/pwm/config/stored/StoredConfigurationModifier.java
  10. 2 1
      server/src/main/java/password/pwm/config/value/NamedSecretValue.java
  11. 2 1
      server/src/main/java/password/pwm/config/value/PasswordValue.java
  12. 2 1
      server/src/main/java/password/pwm/config/value/PrivateKeyValue.java
  13. 14 3
      server/src/main/java/password/pwm/http/PwmHttpRequestWrapper.java
  14. 18 8
      server/src/main/java/password/pwm/http/filter/SessionFilter.java
  15. 2 1
      server/src/main/java/password/pwm/http/servlet/configeditor/function/AbstractUriCertImportFunction.java
  16. 0 1
      server/src/main/java/password/pwm/http/servlet/configeditor/function/ActionCertViewerFunction.java
  17. 0 1
      server/src/main/java/password/pwm/http/servlet/configeditor/function/RemoteWebServiceCertViewerFunction.java
  18. 3 2
      server/src/main/java/password/pwm/http/servlet/configeditor/function/SettingUIFunction.java
  19. 4 3
      server/src/main/java/password/pwm/http/servlet/configeditor/function/UserMatchViewerFunction.java
  20. 0 1
      server/src/main/java/password/pwm/http/servlet/configeditor/function/X509CertViewerFunction.java
  21. 3 2
      server/src/main/java/password/pwm/http/servlet/peoplesearch/PeopleSearchServlet.java
  22. 14 2
      server/src/main/java/password/pwm/http/servlet/resource/ResourceFileRequest.java
  23. 8 2
      server/src/main/java/password/pwm/svc/httpclient/ApachePwmHttpClient.java
  24. 2 2
      server/src/main/java/password/pwm/svc/httpclient/JavaPwmHttpClient.java
  25. 0 3
      server/src/main/java/password/pwm/svc/httpclient/PwmHttpClient.java
  26. 2 2
      server/src/main/java/password/pwm/svc/intruder/IntruderDataStore.java
  27. 1 1
      server/src/main/java/password/pwm/svc/intruder/IntruderRecordStore.java
  28. 1 2
      server/src/main/java/password/pwm/svc/intruder/IntruderSystemService.java
  29. 1 5
      server/src/main/java/password/pwm/svc/report/ReportCsvUtility.java
  30. 24 0
      server/src/main/java/password/pwm/util/cli/CliParameters.java
  31. 15 11
      server/src/main/java/password/pwm/util/cli/commands/AbstractCliCommand.java
  32. 19 1
      server/src/main/java/password/pwm/util/cli/commands/ClearResponsesCommand.java
  33. 0 4
      server/src/main/java/password/pwm/util/cli/commands/CliCommand.java
  34. 2 1
      server/src/main/java/password/pwm/util/cli/commands/ConfigDeleteCommand.java
  35. 5 2
      server/src/main/java/password/pwm/util/cli/commands/ConfigLockCommand.java
  36. 3 1
      server/src/main/java/password/pwm/util/cli/commands/ConfigNewCommand.java
  37. 4 1
      server/src/main/java/password/pwm/util/cli/commands/ConfigResetHttpsCommand.java
  38. 4 1
      server/src/main/java/password/pwm/util/cli/commands/ConfigSetPasswordCommand.java
  39. 5 2
      server/src/main/java/password/pwm/util/cli/commands/ConfigUnlockCommand.java
  40. 3 1
      server/src/main/java/password/pwm/util/cli/commands/ExportAuditCommand.java
  41. 13 22
      server/src/main/java/password/pwm/util/cli/commands/ExportHttpsKeyStoreCommand.java
  42. 2 2
      server/src/main/java/password/pwm/util/cli/commands/ExportHttpsTomcatConfigCommand.java
  43. 2 1
      server/src/main/java/password/pwm/util/cli/commands/ExportLocalDBCommand.java
  44. 3 1
      server/src/main/java/password/pwm/util/cli/commands/ExportLogsCommand.java
  45. 50 24
      server/src/main/java/password/pwm/util/cli/commands/ExportResponsesCommand.java
  46. 2 1
      server/src/main/java/password/pwm/util/cli/commands/ExportStatsCommand.java
  47. 2 1
      server/src/main/java/password/pwm/util/cli/commands/ExportWordlistCommand.java
  48. 2 1
      server/src/main/java/password/pwm/util/cli/commands/HelpCommand.java
  49. 6 44
      server/src/main/java/password/pwm/util/cli/commands/ImportHttpsKeyStoreCommand.java
  50. 2 1
      server/src/main/java/password/pwm/util/cli/commands/ImportLocalDBCommand.java
  51. 2 1
      server/src/main/java/password/pwm/util/cli/commands/ImportPropertyConfigCommand.java
  52. 63 44
      server/src/main/java/password/pwm/util/cli/commands/ImportResponsesCommand.java
  53. 21 4
      server/src/main/java/password/pwm/util/cli/commands/LdapSchemaExtendCommand.java
  54. 4 3
      server/src/main/java/password/pwm/util/cli/commands/LocalDBInfoCommand.java
  55. 3 1
      server/src/main/java/password/pwm/util/cli/commands/ResetInstanceIDCommand.java
  56. 26 7
      server/src/main/java/password/pwm/util/cli/commands/ResponseStatsCommand.java
  57. 3 1
      server/src/main/java/password/pwm/util/cli/commands/ShellCommand.java
  58. 2 1
      server/src/main/java/password/pwm/util/cli/commands/TokenInfoCommand.java
  59. 1 2
      server/src/main/java/password/pwm/util/cli/commands/UserReportCommand.java
  60. 3 1
      server/src/main/java/password/pwm/util/cli/commands/VersionCommand.java
  61. 4 1
      server/src/main/java/password/pwm/util/debug/AppItemGenerator.java
  62. 2 1
      server/src/main/java/password/pwm/util/debug/AppPropertiesItemGenerator.java
  63. 3 1
      server/src/main/java/password/pwm/util/debug/BuildManifestDebugItemGenerator.java
  64. 4 2
      server/src/main/java/password/pwm/util/debug/CacheServiceDebugItemGenerator.java
  65. 5 2
      server/src/main/java/password/pwm/util/debug/ClusterInfoDebugGenerator.java
  66. 4 2
      server/src/main/java/password/pwm/util/debug/ConfigurationDebugJsonItemGenerator.java
  67. 3 1
      server/src/main/java/password/pwm/util/debug/ConfigurationDebugTextItemGenerator.java
  68. 4 1
      server/src/main/java/password/pwm/util/debug/ConfigurationFileItemGenerator.java
  69. 5 2
      server/src/main/java/password/pwm/util/debug/DashboardDataDebugItemGenerator.java
  70. 2 1
      server/src/main/java/password/pwm/util/debug/DebugItemGenerator.java
  71. 4 1
      server/src/main/java/password/pwm/util/debug/DomainItemGenerator.java
  72. 3 1
      server/src/main/java/password/pwm/util/debug/FileInfoDebugItemGenerator.java
  73. 4 2
      server/src/main/java/password/pwm/util/debug/HealthDebugItemGenerator.java
  74. 4 1
      server/src/main/java/password/pwm/util/debug/IntruderDataGenerator.java
  75. 4 1
      server/src/main/java/password/pwm/util/debug/LDAPPermissionItemGenerator.java
  76. 3 1
      server/src/main/java/password/pwm/util/debug/LdapConnectionsDebugItemGenerator.java
  77. 3 1
      server/src/main/java/password/pwm/util/debug/LdapDebugItemGenerator.java
  78. 5 2
      server/src/main/java/password/pwm/util/debug/LdapRecentUserDebugGenerator.java
  79. 4 2
      server/src/main/java/password/pwm/util/debug/LocalDBDebugGenerator.java
  80. 4 2
      server/src/main/java/password/pwm/util/debug/LogDebugItemGenerator.java
  81. 4 2
      server/src/main/java/password/pwm/util/debug/LogJsonItemGenerator.java
  82. 4 2
      server/src/main/java/password/pwm/util/debug/RootFileSystemDebugItemGenerator.java
  83. 5 2
      server/src/main/java/password/pwm/util/debug/ServicesDebugItemGenerator.java
  84. 3 1
      server/src/main/java/password/pwm/util/debug/SessionDataGenerator.java
  85. 3 1
      server/src/main/java/password/pwm/util/debug/StatisticsDataDebugItemGenerator.java
  86. 4 1
      server/src/main/java/password/pwm/util/debug/StatisticsEpsDataDebugItemGenerator.java
  87. 3 1
      server/src/main/java/password/pwm/util/debug/SystemEnvironmentItemGenerator.java
  88. 3 1
      server/src/main/java/password/pwm/util/debug/ThreadDumpDebugItemGenerator.java
  89. 4 1
      server/src/main/java/password/pwm/util/java/CachingProxyWrapper.java
  90. 2 0
      server/src/main/java/password/pwm/util/java/Memorizer.java
  91. 2 2
      server/src/main/java/password/pwm/util/json/MoshiJsonServiceProvider.java
  92. 0 1
      server/src/main/java/password/pwm/util/logging/PwmLogEvent.java
  93. 25 8
      server/src/main/java/password/pwm/util/secure/self/SelfCertFactory.java

+ 13 - 2
build/spotbugs-exclude.xml

@@ -62,9 +62,20 @@
         <Bug pattern="MRC_METHOD_RETURNS_CONSTANT" />
     </Match>
 
+    <Match>
+        <!-- issue with spotbugs 4.7.0 -->
+        <!-- https://github.com/spotbugs/spotbugs/issues/2040 -->
+        <Bug pattern="THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION" />
+    </Match>
 
 
-
-
+    <!-- jsp exclusions -->
+    <Match>
+        <Or>
+            <Class name="~^jsp\..*_jsp$" />
+        </Or>
+        <!-- pretty much every line in jsp throws throwable :) -->
+        <Bug pattern="THROWS_METHOD_THROWS_CLAUSE_THROWABLE" />
+    </Match>
 
 </FindBugsFilter>

+ 1 - 1
data-service/pom.xml

@@ -212,7 +212,7 @@
         <dependency>
             <groupId>ch.qos.reload4j</groupId>
             <artifactId>reload4j</artifactId>
-            <version>1.2.20</version>
+            <version>1.2.21</version>
         </dependency>
         <dependency>
             <groupId>org.jdom</groupId>

+ 5 - 0
lib-util/src/main/java/password/pwm/util/java/LazySupplier.java

@@ -20,6 +20,8 @@
 
 package password.pwm.util.java;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
 import java.util.function.Supplier;
 
 /**
@@ -51,6 +53,7 @@ public class LazySupplier<T> implements Supplier<T>
         return value;
     }
 
+    @SuppressFBWarnings( "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION" )
     public interface CheckedSupplier<T, E extends Exception>
     {
         T call() throws E;
@@ -61,6 +64,7 @@ public class LazySupplier<T> implements Supplier<T>
         return new LazyCheckedSupplier<>( lazySupplier );
     }
 
+    @SuppressFBWarnings( "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION" )
     private static class LazyCheckedSupplier<T, E extends Exception> implements CheckedSupplier<T, E>
     {
         private boolean supplied = false;
@@ -73,6 +77,7 @@ public class LazySupplier<T> implements Supplier<T>
         }
 
         @Override
+        @SuppressFBWarnings( "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION" )
         public T call() throws E
         {
             if ( !supplied )

+ 4 - 8
lib-util/src/main/java/password/pwm/util/java/StringUtil.java

@@ -20,7 +20,6 @@
 
 package password.pwm.util.java;
 
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import org.apache.commons.codec.binary.Base32;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.text.StringEscapeUtils;
@@ -279,7 +278,6 @@ public abstract class StringUtil
         return StringEscapeUtils.escapeXml11( input );
     }
 
-    @SuppressFBWarnings( "EXS_EXCEPTION_SOFTENING_NO_CONSTRAINTS" )
     public static String urlEncode( final String input )
     {
         try
@@ -288,12 +286,12 @@ public abstract class StringUtil
         }
         catch ( final UnsupportedEncodingException e )
         {
-            throw new RuntimeException( "unexpected error during url encoding: " + e.getMessage(), e );
+            throw new IllegalStateException( "unexpected error during url encoding: " + e.getMessage(), e );
         }
     }
 
-    @SuppressFBWarnings( "EXS_EXCEPTION_SOFTENING_NO_CONSTRAINTS" )
     public static String urlDecode( final String input )
+            throws IOException
     {
         try
         {
@@ -301,7 +299,7 @@ public abstract class StringUtil
         }
         catch ( final UnsupportedEncodingException e )
         {
-            throw new RuntimeException( "unexpected error during url decoding: " + e.getMessage(), e );
+            throw new IOException( "unexpected error during url decoding: " + e.getMessage(), e );
         }
     }
 
@@ -312,7 +310,6 @@ public abstract class StringUtil
         return new String( base32.encode( input ), STRING_UTIL_CHARSET.toString() );
     }
 
-    @SuppressFBWarnings( "EXS_EXCEPTION_SOFTENING_NO_CONSTRAINTS" )
     public static byte[] base64Decode( final CharSequence input, final StringUtil.Base64Options... options )
             throws IOException
     {
@@ -341,7 +338,6 @@ public abstract class StringUtil
         }
     }
 
-    @SuppressFBWarnings( "EXS_EXCEPTION_SOFTENING_NO_CONSTRAINTS" )
     public static String base64Encode( final byte[] input, final StringUtil.Base64Options... options )
     {
         final byte[] compressedBytes;
@@ -353,7 +349,7 @@ public abstract class StringUtil
             }
             catch ( final IOException e )
             {
-                throw new RuntimeException( "unexpected error during base64 decoding: " + e, e );
+                throw new IllegalStateException( "unexpected error during base64 decoding: " + e, e );
             }
         }
         else

+ 1 - 1
onejar/pom.xml

@@ -16,7 +16,7 @@
     <name>PWM Password Self Service: Executable Server JAR</name>
 
     <properties>
-        <tomcat.version>9.0.62</tomcat.version>
+        <tomcat.version>9.0.63</tomcat.version>
     </properties>
 
     <build>

+ 2 - 2
pom.xml

@@ -339,7 +339,7 @@
                     <dependency>
                         <groupId>com.github.spotbugs</groupId>
                         <artifactId>spotbugs</artifactId>
-                        <version>4.6.0</version>
+                        <version>4.7.0</version>
                     </dependency>
                 </dependencies>
                 <configuration>
@@ -458,7 +458,7 @@
         <dependency>
             <groupId>com.github.spotbugs</groupId>
             <artifactId>spotbugs-annotations</artifactId>
-            <version>4.6.0</version>
+            <version>4.7.0</version>
             <scope>provided</scope>
         </dependency>
 

+ 1 - 1
server/pom.xml

@@ -256,7 +256,7 @@
         <dependency>
             <groupId>ch.qos.reload4j</groupId>
             <artifactId>reload4j</artifactId>
-            <version>1.2.20</version>
+            <version>1.2.21</version>
         </dependency>
         <dependency>
             <groupId>org.jasig.cas.client</groupId>

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

@@ -109,7 +109,6 @@ class PwmDomainUtil
 
         @Override
         public Optional<PwmUnrecoverableException> call()
-                throws Exception
         {
             try
             {

+ 4 - 2
server/src/main/java/password/pwm/config/stored/StoredConfigurationModifier.java

@@ -27,6 +27,7 @@ import password.pwm.config.value.StoredValue;
 import password.pwm.config.value.StringValue;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
+import password.pwm.error.PwmInternalException;
 import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.i18n.PwmLocaleBundle;
@@ -219,7 +220,8 @@ public class StoredConfigurationModifier
         this.writeConfigProperty( ConfigurationProperty.PASSWORD_HASH, passwordHash );
     }
 
-    private void update( final FunctionWithException<StoredConfigData> function ) throws PwmUnrecoverableException
+    private void update( final FunctionWithException<StoredConfigData> function )
+            throws PwmUnrecoverableException
     {
         try
         {
@@ -231,7 +233,7 @@ public class StoredConfigurationModifier
                 }
                 catch ( final PwmUnrecoverableException e )
                 {
-                    throw new RuntimeException( e );
+                    throw new PwmInternalException( e );
                 }
             } );
             modifications.incrementAndGet();

+ 2 - 1
server/src/main/java/password/pwm/config/value/NamedSecretValue.java

@@ -29,6 +29,7 @@ import password.pwm.config.stored.XmlOutputProcessData;
 import password.pwm.config.value.data.NamedSecretData;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
+import password.pwm.error.PwmInternalException;
 import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.PasswordData;
@@ -200,7 +201,7 @@ public class NamedSecretValue implements StoredValue
         }
         catch ( final Exception e )
         {
-            throw new RuntimeException( "missing required AES and SHA1 libraries, or other crypto fault: " + e.getMessage() );
+            throw new PwmInternalException( "missing required AES and SHA1 libraries, or other crypto fault: " + e.getMessage() );
         }
         return Collections.unmodifiableList( valuesElement );
     }

+ 2 - 1
server/src/main/java/password/pwm/config/value/PasswordValue.java

@@ -29,6 +29,7 @@ import password.pwm.config.stored.StoredConfigXmlConstants;
 import password.pwm.config.stored.XmlOutputProcessData;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
+import password.pwm.error.PwmInternalException;
 import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.PasswordData;
@@ -174,7 +175,7 @@ public class PasswordValue implements StoredValue
         }
         catch ( final Exception e )
         {
-            throw new RuntimeException( "missing required AES and SHA1 libraries, or other crypto fault: " + e.getMessage() );
+            throw new PwmInternalException( "missing required AES and SHA1 libraries, or other crypto fault: " + e.getMessage() );
         }
         return Collections.singletonList( valueElement );
     }

+ 2 - 1
server/src/main/java/password/pwm/config/value/PrivateKeyValue.java

@@ -26,6 +26,7 @@ import password.pwm.bean.PrivateKeyCertificate;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.stored.StoredConfigXmlConstants;
 import password.pwm.config.stored.XmlOutputProcessData;
+import password.pwm.error.PwmInternalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.json.JsonFactory;
@@ -201,7 +202,7 @@ public class PrivateKeyValue extends AbstractValue
             }
             catch ( final Exception e )
             {
-                throw new RuntimeException( "missing required AES and SHA1 libraries, or other crypto fault: " + e.getMessage() );
+                throw new PwmInternalException( "missing required AES and SHA1 libraries, or other crypto fault: " + e.getMessage() );
             }
         }
         return Collections.singletonList( valueElement );

+ 14 - 3
server/src/main/java/password/pwm/http/PwmHttpRequestWrapper.java

@@ -32,8 +32,9 @@ import password.pwm.util.ServletUtility;
 import password.pwm.util.Validator;
 import password.pwm.util.java.CollectionUtil;
 import password.pwm.util.java.JavaHelper;
-import password.pwm.util.json.JsonFactory;
 import password.pwm.util.java.StringUtil;
+import password.pwm.util.json.JsonFactory;
+import password.pwm.util.logging.PwmLogger;
 
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
@@ -54,6 +55,8 @@ import java.util.stream.Collectors;
 
 public class PwmHttpRequestWrapper
 {
+    private static final PwmLogger LOGGER = PwmLogger.forClass( PwmHttpRequestWrapper.class );
+
     private final HttpServletRequest httpServletRequest;
     private final AppConfig appConfig;
 
@@ -409,8 +412,16 @@ public class PwmHttpRequestWrapper
                 if ( cookie.getName() != null && cookie.getName().equals( cookieName ) )
                 {
                     final String rawCookieValue = cookie.getValue();
-                    final String decodedCookieValue = StringUtil.urlDecode( rawCookieValue );
-                    return Optional.of( Validator.sanitizeInputValue( appConfig, decodedCookieValue, maxChars ) );
+                    try
+                    {
+                        final String decodedCookieValue = StringUtil.urlDecode( rawCookieValue );
+                        return Optional.of( Validator.sanitizeInputValue( appConfig, decodedCookieValue, maxChars ) );
+                    }
+                    catch ( final IOException e )
+                    {
+                        LOGGER.trace( () -> "error decoding cookie value '" + cookie.getName()
+                                + "', error: " + e.getMessage() );
+                    }
                 }
             }
         }

+ 18 - 8
server/src/main/java/password/pwm/http/filter/SessionFilter.java

@@ -328,21 +328,31 @@ public class SessionFilter extends AbstractPwmFilter
             {
                 for ( final String paramName : pwmRequest.parameterNames() )
                 {
-                    // check to make sure param is in query string
-                    if ( queryString.contains( StringUtil.urlDecode( paramName ) ) )
+                    try
                     {
-                        if ( !verificationParamName.equals( paramName ) )
+                        final String decodedParamName = StringUtil.urlDecode( paramName );
+
+                        // check to make sure param is in query string
+                        if ( queryString.contains( decodedParamName ) )
                         {
-                            // raw read of param value to avoid sanitization checks
-                            for ( final String value : req.getParameterValues( paramName ) )
+                            if ( !verificationParamName.equals( paramName ) )
                             {
-                                redirectURL = PwmURL.appendAndEncodeUrlParameters( redirectURL, paramName, value );
+                                // raw read of param value to avoid sanitization checks
+                                for ( final String value : req.getParameterValues( paramName ) )
+                                {
+                                    redirectURL = PwmURL.appendAndEncodeUrlParameters( redirectURL, paramName, value );
+                                }
                             }
                         }
+                        else
+                        {
+                            LOGGER.debug( () -> "dropping non-query string (body?) parameter '" + paramName + "' during redirect validation)" );
+                        }
                     }
-                    else
+                    catch ( final IOException e )
                     {
-                        LOGGER.debug( () -> "dropping non-query string (body?) parameter '" + paramName + "' during redirect validation)" );
+                        LOGGER.trace( () -> "error decoding cookie value '" + paramName
+                                + "', error: " + e.getMessage() );
                     }
                 }
             }

+ 2 - 1
server/src/main/java/password/pwm/http/servlet/configeditor/function/AbstractUriCertImportFunction.java

@@ -46,7 +46,8 @@ abstract class AbstractUriCertImportFunction implements SettingUIFunction
             final PwmRequest pwmRequest,
             final StoredConfigurationModifier modifier,
             final StoredConfigKey key,
-            final String extraData )
+            final String extraData
+    )
             throws PwmOperationalException, PwmUnrecoverableException
     {
         final PwmSession pwmSession = pwmRequest.getPwmSession();

+ 0 - 1
server/src/main/java/password/pwm/http/servlet/configeditor/function/ActionCertViewerFunction.java

@@ -43,7 +43,6 @@ public class ActionCertViewerFunction implements SettingUIFunction
             final StoredConfigKey key,
             final String extraData
     )
-            throws Exception
     {
         final Map<String, Object> parsedExtraData = JsonFactory.get().deserializeMap( extraData, String.class, Object.class );
         final int iteration = Integer.parseInt( parsedExtraData.get( "iteration" ).toString() );

+ 0 - 1
server/src/main/java/password/pwm/http/servlet/configeditor/function/RemoteWebServiceCertViewerFunction.java

@@ -43,7 +43,6 @@ public class RemoteWebServiceCertViewerFunction implements SettingUIFunction
             final StoredConfigKey key,
             final String extraData
     )
-            throws Exception
     {
         final Map<String, Object> parsedExtraData = JsonFactory.get().deserializeMap( extraData, String.class, Object.class );
         final int iteration = Integer.parseInt( parsedExtraData.get( "iteration" ).toString() );

+ 3 - 2
server/src/main/java/password/pwm/http/servlet/configeditor/function/SettingUIFunction.java

@@ -22,6 +22,8 @@ package password.pwm.http.servlet.configeditor.function;
 
 import password.pwm.config.stored.StoredConfigKey;
 import password.pwm.config.stored.StoredConfigurationModifier;
+import password.pwm.error.PwmOperationalException;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.PwmRequest;
 
 import java.io.Serializable;
@@ -36,6 +38,5 @@ public interface SettingUIFunction
             StoredConfigurationModifier modifier,
             StoredConfigKey key,
             String extraData
-    )
-            throws Exception;
+    ) throws PwmOperationalException, PwmUnrecoverableException;
 }

+ 4 - 3
server/src/main/java/password/pwm/http/servlet/configeditor/function/UserMatchViewerFunction.java

@@ -72,8 +72,9 @@ public class UserMatchViewerFunction implements SettingUIFunction
             final PwmRequest pwmRequest,
             final StoredConfigurationModifier storedConfiguration,
             final StoredConfigKey key,
-            final String extraData )
-            throws Exception
+            final String extraData
+    )
+            throws PwmUnrecoverableException, PwmOperationalException
     {
         final PwmDomain pwmDomain = pwmRequest.getPwmDomain();
 
@@ -108,7 +109,7 @@ public class UserMatchViewerFunction implements SettingUIFunction
             final StoredConfiguration storedConfiguration,
             final StoredConfigKey key
     )
-            throws Exception
+            throws PwmUnrecoverableException, PwmOperationalException
     {
         final AppConfig config = new AppConfig( storedConfiguration );
         final PwmApplication tempApplication = PwmApplication.createPwmApplication( pwmDomain.getPwmApplication().getPwmEnvironment().makeRuntimeInstance( config ) );

+ 0 - 1
server/src/main/java/password/pwm/http/servlet/configeditor/function/X509CertViewerFunction.java

@@ -43,7 +43,6 @@ public class X509CertViewerFunction implements SettingUIFunction
             final StoredConfigKey key,
             final String extraData
     )
-            throws Exception
     {
         final List<Map<String, String>> certificateInfos = makeCertDebugMap( key, modifier );
         return ( Serializable ) certificateInfos;

+ 3 - 2
server/src/main/java/password/pwm/http/servlet/peoplesearch/PeopleSearchServlet.java

@@ -97,7 +97,8 @@ public abstract class PeopleSearchServlet extends ControlledPwmServlet
     }
 
     @Override
-    protected void nextStep( final PwmRequest pwmRequest ) throws PwmUnrecoverableException, IOException, ChaiUnavailableException, ServletException
+    protected void nextStep( final PwmRequest pwmRequest )
+            throws PwmUnrecoverableException, IOException, ChaiUnavailableException, ServletException
     {
         if ( pwmRequest.getURL().isPublicUrl() )
         {
@@ -227,7 +228,7 @@ public abstract class PeopleSearchServlet extends ControlledPwmServlet
 
     @ActionHandler( action = "photo" )
     public ProcessStatus processUserPhotoImageRequest( final PwmRequest pwmRequest )
-            throws ChaiUnavailableException, PwmUnrecoverableException, IOException, ServletException
+            throws PwmUnrecoverableException, IOException, ServletException
     {
         final String userKey = pwmRequest.readParameterAsString( PARAM_USERKEY, PwmHttpRequestWrapper.Flag.BypassValidation );
         if ( userKey.length() < 1 )

+ 14 - 2
server/src/main/java/password/pwm/http/servlet/resource/ResourceFileRequest.java

@@ -37,6 +37,7 @@ import password.pwm.util.logging.PwmLogger;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.time.Instant;
 import java.util.Arrays;
@@ -67,7 +68,7 @@ class ResourceFileRequest
             @NonNull final ResourceServletConfiguration resourceServletConfiguration,
             @NonNull final HttpServletRequest httpServletRequest
     )
-            throws PwmUnrecoverableException
+            throws PwmUnrecoverableException, IOException
     {
         this.domainConfig = domainConfig;
         this.resourceServletConfiguration = resourceServletConfiguration;
@@ -182,6 +183,7 @@ class ResourceFileRequest
             final DomainConfig domainConfig,
             final String inputResourcePathUri
     )
+            throws IOException
     {
         // URL-decode the file name (might contain spaces and on) and prepare file object.
         String effectiveUri = StringUtil.urlDecode( inputResourcePathUri );
@@ -212,7 +214,17 @@ class ResourceFileRequest
     )
             throws PwmUnrecoverableException
     {
-        final String effectiveUri = deriveEffectiveURI( domainConfig, inputResourcePathUri );
+        final String effectiveUri;
+        try
+        {
+            effectiveUri = deriveEffectiveURI( domainConfig, inputResourcePathUri );
+        }
+        catch ( final IOException e )
+        {
+            final String errorMsg = "i/o error during resource request resolution: " + e.getMessage();
+            LOGGER.trace( () -> errorMsg );
+            throw new PwmUnrecoverableException( PwmError.ERROR_INTERNAL, errorMsg );
+        }
 
         if ( !effectiveUri.startsWith( ResourceFileServlet.RESOURCE_PATH ) )
         {

+ 8 - 2
server/src/main/java/password/pwm/svc/httpclient/ApachePwmHttpClient.java

@@ -144,10 +144,16 @@ public class ApachePwmHttpClient implements AutoCloseable, PwmHttpClientProvider
 
     @Override
     public void close()
-            throws Exception
     {
         LOGGER.trace( () -> "closed client #" + clientID );
-        httpClient.close();
+        try
+        {
+            httpClient.close();
+        }
+        catch ( final IOException e )
+        {
+            LOGGER.trace( () -> "error closing ApacheHttpClient: " + e.getMessage() );
+        }
         open = false;
     }
 

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

@@ -129,9 +129,9 @@ public class JavaPwmHttpClient implements PwmHttpClientProvider
     }
 
     @Override
-    public void close() throws Exception
+    public void close()
     {
-
+        // Java HttpClient has no close()
     }
 
     @Override

+ 0 - 3
server/src/main/java/password/pwm/svc/httpclient/PwmHttpClient.java

@@ -34,9 +34,6 @@ import java.util.List;
 
 public interface PwmHttpClient extends AutoCloseable
 {
-    void close()
-            throws Exception;
-
     boolean isOpen();
 
     PwmHttpClientResponse makeRequest(

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

@@ -136,7 +136,7 @@ class IntruderDataStore implements IntruderRecordStore
 
     @Override
     public ClosableIterator<IntruderRecord> iterator()
-            throws PwmOperationalException, PwmUnrecoverableException
+            throws PwmUnrecoverableException
     {
         try
         {
@@ -144,7 +144,7 @@ class IntruderDataStore implements IntruderRecordStore
         }
         catch ( final PwmDataStoreException e )
         {
-            throw new PwmOperationalException( PwmError.ERROR_INTERNAL, "iterator unavailable:" + e.getMessage() );
+            throw new PwmUnrecoverableException( PwmError.ERROR_INTERNAL, "iterator unavailable:" + e.getMessage() );
         }
     }
 

+ 1 - 1
server/src/main/java/password/pwm/svc/intruder/IntruderRecordStore.java

@@ -37,7 +37,7 @@ interface IntruderRecordStore
 
     void write( String key, IntruderRecord record ) throws PwmOperationalException, PwmUnrecoverableException;
 
-    ClosableIterator<IntruderRecord> iterator( ) throws PwmOperationalException, PwmUnrecoverableException;
+    ClosableIterator<IntruderRecord> iterator( ) throws PwmUnrecoverableException;
 
     void cleanup( TimeDuration maxRecordAge ) throws LocalDBException;
 

+ 1 - 2
server/src/main/java/password/pwm/svc/intruder/IntruderSystemService.java

@@ -31,7 +31,6 @@ import password.pwm.config.option.IntruderStorageMethod;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmException;
-import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.health.HealthRecord;
 import password.pwm.svc.AbstractPwmService;
@@ -116,7 +115,7 @@ public class IntruderSystemService extends AbstractPwmService implements PwmServ
     }
 
     public ClosableIterator<PublicIntruderRecord> allRecordIterator()
-            throws PwmUnrecoverableException, PwmOperationalException
+            throws PwmUnrecoverableException
     {
         final ClosableIterator<IntruderRecord> innerIterator = recordStore.iterator();
         return new ClosableIterator<>()

+ 1 - 5
server/src/main/java/password/pwm/svc/report/ReportCsvUtility.java

@@ -20,14 +20,10 @@
 
 package password.pwm.svc.report;
 
-import com.novell.ldapchai.exception.ChaiOperationException;
-import com.novell.ldapchai.exception.ChaiUnavailableException;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import org.apache.commons.csv.CSVPrinter;
 import password.pwm.PwmApplication;
 import password.pwm.config.SettingReader;
-import password.pwm.error.PwmOperationalException;
-import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.i18n.Display;
 import password.pwm.i18n.PwmDisplayBundle;
 import password.pwm.util.i18n.LocaleHelper;
@@ -72,7 +68,7 @@ public class ReportCsvUtility
     }
 
     public void outputToCsv( final OutputStream outputStream, final boolean includeHeader, final Locale locale )
-            throws IOException, ChaiUnavailableException, ChaiOperationException, PwmUnrecoverableException, PwmOperationalException
+            throws IOException
     {
         final SettingReader config = pwmApplication.getConfig();
 

+ 24 - 0
server/src/main/java/password/pwm/util/cli/CliParameters.java

@@ -48,6 +48,30 @@ public class CliParameters
         String getName( );
     }
 
+    public static Option newRequiredStringOption( final String name )
+    {
+        return  new CliParameters.Option()
+        {
+            @Override
+            public boolean isOptional()
+            {
+                return false;
+            }
+
+            @Override
+            public Type getType()
+            {
+                return Type.STRING;
+            }
+
+            @Override
+            public String getName()
+            {
+                return name;
+            }
+        };
+    }
+
     public static final Option REQUIRED_NEW_OUTPUT_FILE = new Option()
     {
         @Override

+ 15 - 11
server/src/main/java/password/pwm/util/cli/commands/AbstractCliCommand.java

@@ -21,11 +21,14 @@
 package password.pwm.util.cli.commands;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import password.pwm.error.PwmException;
 import password.pwm.util.cli.CliEnvironment;
+import password.pwm.util.cli.CliException;
 import password.pwm.util.cli.CliParameters;
 
 import java.io.Console;
 import java.io.IOException;
+import java.io.Writer;
 import java.nio.charset.Charset;
 import java.util.Scanner;
 
@@ -38,18 +41,16 @@ public abstract class AbstractCliCommand implements CliCommand
     }
 
     void out( final CharSequence out )
+            throws IOException
     {
-        if ( cliEnvironment != null && cliEnvironment.getDebugWriter() != null )
+        if ( cliEnvironment != null )
         {
-            try
-            {
-                cliEnvironment.getDebugWriter().append( out );
-                cliEnvironment.getDebugWriter().append( '\n' );
-                cliEnvironment.getDebugWriter().flush();
-            }
-            catch ( final IOException e )
+            final Writer debugWriter = cliEnvironment.getDebugWriter();
+            if ( debugWriter != null )
             {
-                throw new RuntimeException( "error writing debug output", e );
+                debugWriter.append( out );
+                debugWriter.append( '\n' );
+                debugWriter.flush();
             }
         }
     }
@@ -59,6 +60,7 @@ public abstract class AbstractCliCommand implements CliCommand
             final String cli,
             final CliEnvironment cliEnvironment
     )
+            throws CliException
     {
         this.cliEnvironment = cliEnvironment;
         try
@@ -67,7 +69,7 @@ public abstract class AbstractCliCommand implements CliCommand
         }
         catch ( final Exception e )
         {
-            throw new RuntimeException( e );
+            throw new CliException( "error executing command: " + e.getMessage() );
         }
     }
 
@@ -92,10 +94,11 @@ public abstract class AbstractCliCommand implements CliCommand
         return true;
     }
 
-    abstract void doCommand( ) throws Exception;
+    abstract void doCommand( ) throws IOException, PwmException, CliException;
 
     @SuppressFBWarnings( "DM_EXIT" )
     String promptForPassword( )
+            throws IOException
     {
         final Console console = System.console();
         console.writer().write( "enter password:" );
@@ -113,6 +116,7 @@ public abstract class AbstractCliCommand implements CliCommand
     }
 
     String getOptionalPassword( )
+            throws IOException
     {
         final String optionName = CliParameters.OPTIONAL_PASSWORD.getName();
         if ( cliEnvironment.getOptions().containsKey( optionName ) )

+ 19 - 1
server/src/main/java/password/pwm/util/cli/commands/ClearResponsesCommand.java

@@ -20,15 +20,19 @@
 
 package password.pwm.util.cli.commands;
 
+import password.pwm.util.cli.CliException;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.localdb.LocalDB;
+import password.pwm.util.localdb.LocalDBException;
+
+import java.io.IOException;
 
 public class ClearResponsesCommand extends AbstractCliCommand
 {
 
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException, CliException
     {
         final String msg = "Proceeding with this operation will clear all stored responses from the LocalDB." + "\n"
                 + "Please consider exporting the responses before proceeding. " + "\n"
@@ -39,6 +43,20 @@ public class ClearResponsesCommand extends AbstractCliCommand
             return;
         }
 
+        try
+        {
+            clearDb();
+        }
+        catch ( final LocalDBException e )
+        {
+            throw new CliException( e.getMessage(), e );
+        }
+
+    }
+
+    private void clearDb()
+            throws LocalDBException, IOException
+    {
         final LocalDB localDB = cliEnvironment.getLocalDB();
 
         if ( localDB.size( LocalDB.DB.RESPONSE_STORAGE ) == 0 )

+ 0 - 4
server/src/main/java/password/pwm/util/cli/commands/CliCommand.java

@@ -26,11 +26,7 @@ import password.pwm.util.cli.CliParameters;
 
 public interface CliCommand
 {
-
-
     void execute( String cli, CliEnvironment cliEnvironment ) throws CliException;
 
     CliParameters getCliParameters( );
-
-
 }

+ 2 - 1
server/src/main/java/password/pwm/util/cli/commands/ConfigDeleteCommand.java

@@ -23,12 +23,13 @@ package password.pwm.util.cli.commands;
 import password.pwm.util.cli.CliParameters;
 
 import java.io.File;
+import java.io.IOException;
 
 public class ConfigDeleteCommand extends AbstractCliCommand
 {
     @Override
     public void doCommand( )
-            throws Exception
+            throws IOException
     {
         final File configurationFile = cliEnvironment.getConfigurationFile();
         if ( configurationFile == null || !configurationFile.exists() )

+ 5 - 2
server/src/main/java/password/pwm/util/cli/commands/ConfigLockCommand.java

@@ -21,19 +21,22 @@
 package password.pwm.util.cli.commands;
 
 import password.pwm.bean.SessionLabel;
-import password.pwm.config.stored.ConfigurationProperty;
 import password.pwm.config.stored.ConfigurationFileManager;
+import password.pwm.config.stored.ConfigurationProperty;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationModifier;
+import password.pwm.error.PwmOperationalException;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.cli.CliParameters;
 
+import java.io.IOException;
 import java.util.Optional;
 
 public class ConfigLockCommand extends AbstractCliCommand
 {
     @Override
     public void doCommand( )
-            throws Exception
+            throws IOException, PwmUnrecoverableException, PwmOperationalException
     {
         final ConfigurationFileManager configurationFileManager = cliEnvironment.getConfigurationFileManager();
         final StoredConfiguration storedConfiguration = configurationFileManager.getStoredConfiguration();

+ 3 - 1
server/src/main/java/password/pwm/util/cli/commands/ConfigNewCommand.java

@@ -22,17 +22,19 @@ package password.pwm.util.cli.commands;
 
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationFactory;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.cli.CliParameters;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.util.Collections;
 
 public class ConfigNewCommand extends AbstractCliCommand
 {
     @Override
     public void doCommand( )
-            throws Exception
+            throws IOException, PwmUnrecoverableException
     {
         final StoredConfiguration storedConfiguration = StoredConfigurationFactory.newConfig();
 

+ 4 - 1
server/src/main/java/password/pwm/util/cli/commands/ConfigResetHttpsCommand.java

@@ -28,16 +28,19 @@ import password.pwm.config.stored.ConfigurationFileManager;
 import password.pwm.config.stored.StoredConfigKey;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationModifier;
+import password.pwm.error.PwmOperationalException;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.cli.CliParameters;
 
 import java.io.File;
+import java.io.IOException;
 
 public class ConfigResetHttpsCommand
         extends AbstractCliCommand
 {
     @Override
     public void doCommand( )
-            throws Exception
+            throws IOException, PwmUnrecoverableException, PwmOperationalException
     {
         final File configurationFile = cliEnvironment.getConfigurationFile();
         if ( configurationFile == null || !configurationFile.exists() )

+ 4 - 1
server/src/main/java/password/pwm/util/cli/commands/ConfigSetPasswordCommand.java

@@ -25,8 +25,11 @@ import password.pwm.config.stored.ConfigurationFileManager;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationModifier;
 import password.pwm.config.stored.StoredConfigurationUtil;
+import password.pwm.error.PwmOperationalException;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.cli.CliParameters;
 
+import java.io.IOException;
 import java.util.Collections;
 
 public class ConfigSetPasswordCommand extends AbstractCliCommand
@@ -34,7 +37,7 @@ public class ConfigSetPasswordCommand extends AbstractCliCommand
 
     @Override
     public void doCommand( )
-            throws Exception
+            throws IOException, PwmUnrecoverableException, PwmOperationalException
     {
         final ConfigurationFileManager configurationFileManager = cliEnvironment.getConfigurationFileManager();
         final StoredConfiguration storedConfiguration = configurationFileManager.getStoredConfiguration();

+ 5 - 2
server/src/main/java/password/pwm/util/cli/commands/ConfigUnlockCommand.java

@@ -21,19 +21,22 @@
 package password.pwm.util.cli.commands;
 
 import password.pwm.bean.SessionLabel;
-import password.pwm.config.stored.ConfigurationProperty;
 import password.pwm.config.stored.ConfigurationFileManager;
+import password.pwm.config.stored.ConfigurationProperty;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationModifier;
+import password.pwm.error.PwmOperationalException;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.cli.CliParameters;
 
+import java.io.IOException;
 import java.util.Optional;
 
 public class ConfigUnlockCommand extends AbstractCliCommand
 {
     @Override
     public void doCommand( )
-            throws Exception
+            throws IOException, PwmUnrecoverableException, PwmOperationalException
     {
         final ConfigurationFileManager configurationFileManager = cliEnvironment.getConfigurationFileManager();
         final StoredConfiguration storedConfiguration = configurationFileManager.getStoredConfiguration();

+ 3 - 1
server/src/main/java/password/pwm/util/cli/commands/ExportAuditCommand.java

@@ -23,6 +23,7 @@ package password.pwm.util.cli.commands;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.bean.DomainID;
+import password.pwm.error.PwmException;
 import password.pwm.svc.event.AuditService;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.java.PwmTimeUtil;
@@ -30,6 +31,7 @@ import password.pwm.util.java.TimeDuration;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.time.Instant;
 import java.util.Collections;
 
@@ -37,7 +39,7 @@ public class ExportAuditCommand extends AbstractCliCommand
 {
     @Override
     void doCommand( )
-            throws Exception
+            throws PwmException, IOException
     {
         final PwmApplication pwmApplication = cliEnvironment.getPwmApplication();
         final AuditService auditManager = new AuditService();

+ 13 - 22
server/src/main/java/password/pwm/util/cli/commands/ExportHttpsKeyStoreCommand.java

@@ -20,12 +20,15 @@
 
 package password.pwm.util.cli.commands;
 
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.PasswordData;
+import password.pwm.util.cli.CliException;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.secure.HttpsServerCertificateManager;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.security.KeyStore;
 import java.util.Arrays;
 
@@ -36,7 +39,7 @@ public class ExportHttpsKeyStoreCommand extends AbstractCliCommand
 
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException, PwmUnrecoverableException, CliException
     {
         final File outputFile = ( File ) cliEnvironment.getOptions().get( CliParameters.REQUIRED_NEW_OUTPUT_FILE.getName() );
         if ( outputFile.exists() )
@@ -52,7 +55,14 @@ public class ExportHttpsKeyStoreCommand extends AbstractCliCommand
 
         try ( FileOutputStream fos = new FileOutputStream( outputFile ) )
         {
-            keyStore.store( fos, password.toCharArray() );
+            try
+            {
+                keyStore.store( fos, password.toCharArray() );
+            }
+            catch ( final Exception e )
+            {
+                throw new CliException( "error writing keystore to file: " + e.getMessage() );
+            }
         }
 
         out( "successfully exported java keystore to " + outputFile.getAbsolutePath() );
@@ -61,26 +71,7 @@ public class ExportHttpsKeyStoreCommand extends AbstractCliCommand
     @Override
     public CliParameters getCliParameters( )
     {
-        final CliParameters.Option aliasValueOption = new CliParameters.Option()
-        {
-            @Override
-            public boolean isOptional( )
-            {
-                return false;
-            }
-
-            @Override
-            public Type getType( )
-            {
-                return Type.STRING;
-            }
-
-            @Override
-            public String getName( )
-            {
-                return ALIAS_OPTIONNAME;
-            }
-        };
+        final CliParameters.Option aliasValueOption = CliParameters.newRequiredStringOption( ALIAS_OPTIONNAME );
 
         final CliParameters cliParameters = new CliParameters();
         cliParameters.commandName = "ExportHttpsKeyStore";

+ 2 - 2
server/src/main/java/password/pwm/util/cli/commands/ExportHttpsTomcatConfigCommand.java

@@ -39,9 +39,9 @@ import java.util.Set;
 
 public class ExportHttpsTomcatConfigCommand extends AbstractCliCommand
 {
-
     @Override
-    void doCommand( ) throws Exception
+    void doCommand( )
+            throws IOException
     {
         final File sourceFile = ( File ) cliEnvironment.getOptions().get( "sourceFile" );
         final File outputFile = ( File ) cliEnvironment.getOptions().get( "outputFile" );

+ 2 - 1
server/src/main/java/password/pwm/util/cli/commands/ExportLocalDBCommand.java

@@ -27,13 +27,14 @@ import password.pwm.util.localdb.LocalDBUtility;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.util.Collections;
 
 public class ExportLocalDBCommand extends AbstractCliCommand
 {
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException
     {
         final LocalDB localDB = cliEnvironment.getLocalDB();
 

+ 3 - 1
server/src/main/java/password/pwm/util/cli/commands/ExportLogsCommand.java

@@ -23,11 +23,13 @@ package password.pwm.util.cli.commands;
 import password.pwm.PwmConstants;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.localdb.LocalDB;
+import password.pwm.util.localdb.LocalDBException;
 import password.pwm.util.localdb.LocalDBStoredQueue;
 import password.pwm.util.logging.PwmLogEvent;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.util.Collections;
@@ -38,7 +40,7 @@ public class ExportLogsCommand extends AbstractCliCommand
 
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException, LocalDBException
     {
         final LocalDB localDB = this.cliEnvironment.getLocalDB();
         final LocalDBStoredQueue logQueue = LocalDBStoredQueue.createLocalDBStoredQueue( null, localDB,

+ 50 - 24
server/src/main/java/password/pwm/util/cli/commands/ExportResponsesCommand.java

@@ -22,20 +22,25 @@ package password.pwm.util.cli.commands;
 
 import com.novell.ldapchai.ChaiUser;
 import com.novell.ldapchai.cr.ResponseSet;
+import com.novell.ldapchai.exception.ChaiValidationException;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.PwmDomain;
 import password.pwm.bean.SessionLabel;
 import password.pwm.bean.UserIdentity;
+import password.pwm.error.PwmOperationalException;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.ldap.search.SearchConfiguration;
 import password.pwm.ldap.search.UserSearchEngine;
+import password.pwm.util.cli.CliException;
 import password.pwm.util.cli.CliParameters;
-import password.pwm.util.json.JsonFactory;
 import password.pwm.util.java.TimeDuration;
+import password.pwm.util.json.JsonFactory;
 import password.pwm.ws.server.rest.RestChallengesServer;
 
 import java.io.BufferedWriter;
 import java.io.File;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.Writer;
 import java.time.Instant;
@@ -48,7 +53,7 @@ public class ExportResponsesCommand extends AbstractCliCommand
 
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException, CliException
     {
         final PwmApplication pwmApplication = cliEnvironment.getPwmApplication();
 
@@ -61,17 +66,26 @@ public class ExportResponsesCommand extends AbstractCliCommand
         {
             for ( final PwmDomain pwmDomain : pwmApplication.domains().values() )
             {
-                counter += doExport( pwmDomain, writer );
+                try
+                {
+                    counter += doExport( pwmDomain, writer );
+                }
+                catch ( final PwmUnrecoverableException | PwmOperationalException | ChaiValidationException e )
+                {
+                    throw new CliException( "error during export responses: " + e.getMessage(), e );
+                }
             }
         }
 
         out( "output complete, " + counter + " responses exported " + TimeDuration.fromCurrent( startTime ).asCompactString() );
     }
 
-    private long doExport( final PwmDomain pwmDomain, final Writer writer ) throws Exception
+    private long doExport(
+            final PwmDomain pwmDomain,
+            final Writer writer
+    )
+            throws PwmUnrecoverableException, PwmOperationalException, IOException, ChaiValidationException
     {
-        final String systemRecordDelimiter = System.getProperty( "line.separator" );
-
         final UserSearchEngine userSearchEngine = pwmDomain.getUserSearchEngine();
         final SearchConfiguration searchConfiguration = SearchConfiguration.builder()
                 .searchTimeout( TimeDuration.MINUTE )
@@ -89,27 +103,39 @@ public class ExportResponsesCommand extends AbstractCliCommand
         int counter = 0;
         for ( final UserIdentity identity : results.keySet() )
         {
-            final ChaiUser user = pwmDomain.getProxiedChaiUser( SessionLabel.CLI_SESSION_LABEL, identity );
-            final Optional<ResponseSet> responseSet = pwmDomain.getCrService().readUserResponseSet( null, identity, user );
-            if ( responseSet.isPresent() )
-            {
-                counter++;
-                out( "found responses for '" + user + "', writing to output." );
-                final RestChallengesServer.JsonChallengesData outputData = new RestChallengesServer.JsonChallengesData();
-                outputData.challenges = responseSet.get().asChallengeBeans( true );
-                outputData.helpdeskChallenges = responseSet.get().asHelpdeskChallengeBeans( true );
-                outputData.minimumRandoms = responseSet.get().getChallengeSet().minimumResponses();
-                outputData.username = identity.toDelimitedKey();
-                writer.write( JsonFactory.get().serialize( outputData ) );
-                writer.write( systemRecordDelimiter );
-            }
-            else
-            {
-                out( "skipping '" + user.toString() + "', no stored responses." );
-            }
+            counter++;
+            outputUser( pwmDomain, identity, writer );
+
         }
         return counter;
+    }
+
+    private void outputUser(
+            final PwmDomain pwmDomain,
+            final UserIdentity identity,
+            final Writer writer
+    )
+            throws PwmUnrecoverableException, ChaiValidationException, IOException
+    {
+        final String systemRecordDelimiter = System.getProperty( "line.separator" );
 
+        final ChaiUser user = pwmDomain.getProxiedChaiUser( SessionLabel.CLI_SESSION_LABEL, identity );
+        final Optional<ResponseSet> responseSet = pwmDomain.getCrService().readUserResponseSet( null, identity, user );
+        if ( responseSet.isPresent() )
+        {
+            out( "found responses for '" + user + "', writing to output." );
+            final RestChallengesServer.JsonChallengesData outputData = new RestChallengesServer.JsonChallengesData();
+            outputData.challenges = responseSet.get().asChallengeBeans( true );
+            outputData.helpdeskChallenges = responseSet.get().asHelpdeskChallengeBeans( true );
+            outputData.minimumRandoms = responseSet.get().getChallengeSet().minimumResponses();
+            outputData.username = identity.toDelimitedKey();
+            writer.write( JsonFactory.get().serialize( outputData ) );
+            writer.write( systemRecordDelimiter );
+        }
+        else
+        {
+            out( "skipping '" + user.toString() + "', no stored responses." );
+        }
     }
 
     @Override

+ 2 - 1
server/src/main/java/password/pwm/util/cli/commands/ExportStatsCommand.java

@@ -28,6 +28,7 @@ import password.pwm.util.java.TimeDuration;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.util.Collections;
 import java.util.Locale;
 
@@ -36,7 +37,7 @@ public class ExportStatsCommand extends AbstractCliCommand
 
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException
     {
         final PwmApplication pwmApplication = cliEnvironment.getPwmApplication();
         final StatisticsService statsManger = pwmApplication.getStatisticsManager();

+ 2 - 1
server/src/main/java/password/pwm/util/cli/commands/ExportWordlistCommand.java

@@ -27,13 +27,14 @@ import password.pwm.util.localdb.LocalDBUtility;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.util.Collections;
 
 public class ExportWordlistCommand extends AbstractCliCommand
 {
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException
     {
         final LocalDB localDB = cliEnvironment.getLocalDB();
 

+ 2 - 1
server/src/main/java/password/pwm/util/cli/commands/HelpCommand.java

@@ -23,6 +23,7 @@ package password.pwm.util.cli.commands;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.cli.MainClass;
 
+import java.io.IOException;
 import java.util.Collections;
 
 public class HelpCommand extends AbstractCliCommand
@@ -30,7 +31,7 @@ public class HelpCommand extends AbstractCliCommand
 
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException
     {
         out( MainClass.helpTextFromCommands( MainClass.COMMANDS.values() ) );
     }

+ 6 - 44
server/src/main/java/password/pwm/util/cli/commands/ImportHttpsKeyStoreCommand.java

@@ -24,6 +24,8 @@ import password.pwm.bean.SessionLabel;
 import password.pwm.config.stored.ConfigurationFileManager;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationModifier;
+import password.pwm.error.PwmOperationalException;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.PasswordData;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.java.StringUtil;
@@ -31,17 +33,17 @@ import password.pwm.util.secure.HttpsServerCertificateManager;
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.IOException;
 import java.util.Arrays;
 
 public class ImportHttpsKeyStoreCommand extends AbstractCliCommand
 {
-
     private static final String ALIAS_OPTIONNAME = "alias";
     private static final String FORMAT_OPTIONNAME = "format";
 
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException, PwmUnrecoverableException, PwmOperationalException
     {
         final File inputFile = ( File ) cliEnvironment.getOptions().get( CliParameters.REQUIRED_EXISTING_INPUT_FILE.getName() );
         if ( inputFile == null || !inputFile.exists() )
@@ -91,48 +93,8 @@ public class ImportHttpsKeyStoreCommand extends AbstractCliCommand
     @Override
     public CliParameters getCliParameters( )
     {
-
-        final CliParameters.Option aliasValueOption = new CliParameters.Option()
-        {
-            @Override
-            public boolean isOptional( )
-            {
-                return false;
-            }
-
-            @Override
-            public Type getType( )
-            {
-                return Type.STRING;
-            }
-
-            @Override
-            public String getName( )
-            {
-                return ALIAS_OPTIONNAME;
-            }
-        };
-
-        final CliParameters.Option formatValueOption = new CliParameters.Option()
-        {
-            @Override
-            public boolean isOptional( )
-            {
-                return false;
-            }
-
-            @Override
-            public Type getType( )
-            {
-                return Type.STRING;
-            }
-
-            @Override
-            public String getName( )
-            {
-                return FORMAT_OPTIONNAME;
-            }
-        };
+        final CliParameters.Option aliasValueOption = CliParameters.newRequiredStringOption( ALIAS_OPTIONNAME );
+        final CliParameters.Option formatValueOption = CliParameters.newRequiredStringOption( FORMAT_OPTIONNAME );
 
         final CliParameters cliParameters = new CliParameters();
         cliParameters.commandName = "ImportHttpsKeyStore";

+ 2 - 1
server/src/main/java/password/pwm/util/cli/commands/ImportLocalDBCommand.java

@@ -26,13 +26,14 @@ import password.pwm.util.localdb.LocalDB;
 import password.pwm.util.localdb.LocalDBUtility;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.Collections;
 
 public class ImportLocalDBCommand extends AbstractCliCommand
 {
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException
     {
         final LocalDB localDB = cliEnvironment.getLocalDB();
 

+ 2 - 1
server/src/main/java/password/pwm/util/cli/commands/ImportPropertyConfigCommand.java

@@ -28,6 +28,7 @@ import password.pwm.util.cli.CliParameters;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Collections;
 
@@ -38,7 +39,7 @@ public class ImportPropertyConfigCommand extends AbstractCliCommand
 {
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException
     {
         final File configFile = cliEnvironment.getConfigurationFile();
 

+ 63 - 44
server/src/main/java/password/pwm/util/cli/commands/ImportResponsesCommand.java

@@ -22,6 +22,7 @@ package password.pwm.util.cli.commands;
 
 import com.novell.ldapchai.ChaiUser;
 import com.novell.ldapchai.cr.ChallengeSet;
+import com.novell.ldapchai.exception.ChaiUnavailableException;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.PwmDomain;
@@ -34,74 +35,92 @@ import password.pwm.config.profile.PwmPasswordPolicy;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.ldap.LdapOperationsHelper;
+import password.pwm.util.cli.CliException;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.ws.server.rest.RestChallengesServer;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.InputStreamReader;
+import java.io.IOException;
 import java.nio.file.Files;
+import java.time.Instant;
 import java.util.Collections;
+import java.util.Iterator;
 
 public class ImportResponsesCommand extends AbstractCliCommand
 {
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException, CliException
     {
         final PwmApplication pwmApplication = cliEnvironment.getPwmApplication();
 
         final File inputFile = ( File ) cliEnvironment.getOptions().get( CliParameters.REQUIRED_EXISTING_INPUT_FILE.getName() );
-        try ( BufferedReader reader = new BufferedReader( new InputStreamReader( Files.newInputStream( inputFile.toPath() ),
-                PwmConstants.DEFAULT_CHARSET.toString() ) ) )
+
+        try
+        {
+            doImport( pwmApplication, inputFile );
+        }
+        catch ( final PwmUnrecoverableException | ChaiUnavailableException e )
+        {
+            throw new CliException( "error during response import command: " + e.getMessage(),  e );
+        }
+    }
+
+    private void doImport( final PwmApplication pwmApplication,  final File inputFile )
+            throws IOException, PwmUnrecoverableException, ChaiUnavailableException
+    {
+        final Iterator<String> lineIterator = Files.lines( inputFile.toPath() ).iterator();
+
+        out( "importing stored responses from " + inputFile.getAbsolutePath() + "...." );
+
+        int counter = 0;
+        final Instant startTime = Instant.now();
+
+        for ( final String line = lineIterator.next(); lineIterator.hasNext(); )
         {
-            out( "importing stored responses from " + inputFile.getAbsolutePath() + "...." );
+            counter++;
+            processInputLine( pwmApplication, line );
+        }
+
+        out( "output complete, " + counter + " responses imported in " + TimeDuration.fromCurrent( startTime ).asCompactString() );
+    }
 
-            int counter = 0;
-            String line;
-            final long startTime = System.currentTimeMillis();
-            while ( ( line = reader.readLine() ) != null )
+    private void processInputLine( final PwmApplication pwmApplication, final String line )
+            throws PwmUnrecoverableException, ChaiUnavailableException, IOException
+    {
+        final RestChallengesServer.JsonChallengesData inputData;
+        inputData = JsonFactory.get().deserialize( line, RestChallengesServer.JsonChallengesData.class );
+
+        final UserIdentity userIdentity = UserIdentity.fromDelimitedKey( SessionLabel.CLI_SESSION_LABEL, inputData.username );
+        final PwmDomain pwmDomain = figureDomain( userIdentity, pwmApplication );
+        final ChaiUser user = pwmDomain.getProxiedChaiUser( SessionLabel.CLI_SESSION_LABEL, userIdentity );
+        if ( user.exists() )
+        {
+            out( "writing responses to user '" + user.getEntryDN() + "'" );
+            try
             {
-                counter++;
-                final RestChallengesServer.JsonChallengesData inputData;
-                inputData = JsonFactory.get().deserialize( line, RestChallengesServer.JsonChallengesData.class );
-
-                final UserIdentity userIdentity = UserIdentity.fromDelimitedKey( SessionLabel.CLI_SESSION_LABEL, inputData.username );
-                final PwmDomain pwmDomain = figureDomain( userIdentity, pwmApplication );
-                final ChaiUser user = pwmDomain.getProxiedChaiUser( SessionLabel.CLI_SESSION_LABEL, userIdentity );
-                if ( user.exists() )
-                {
-                    out( "writing responses to user '" + user.getEntryDN() + "'" );
-                    try
-                    {
-                        final ChallengeProfile challengeProfile = pwmDomain.getCrService().readUserChallengeProfile(
-                                null, userIdentity, user, PwmPasswordPolicy.defaultPolicy(), PwmConstants.DEFAULT_LOCALE );
-                        final ChallengeSet challengeSet = challengeProfile.getChallengeSet()
-                                .orElseThrow( () -> new PwmUnrecoverableException( PwmError.ERROR_NO_CHALLENGES.toInfo() ) );
-                        final String userGuid = LdapOperationsHelper.readLdapGuidValue( pwmDomain, null, userIdentity, false );
-                        final ResponseInfoBean responseInfoBean = inputData.toResponseInfoBean( PwmConstants.DEFAULT_LOCALE, challengeSet.getIdentifier() );
-                        pwmDomain.getCrService().writeResponses( null, userIdentity, user, userGuid, responseInfoBean );
-                    }
-                    catch ( final Exception e )
-                    {
-                        out( "error writing responses to user '" + user.getEntryDN() + "', error: " + e.getMessage() );
-                        return;
-                    }
-                }
-                else
-                {
-                    out( "user '" + user.getEntryDN() + "' is not a valid userDN" );
-                    return;
-                }
+                final ChallengeProfile challengeProfile = pwmDomain.getCrService().readUserChallengeProfile(
+                        null, userIdentity, user, PwmPasswordPolicy.defaultPolicy(), PwmConstants.DEFAULT_LOCALE );
+                final ChallengeSet challengeSet = challengeProfile.getChallengeSet()
+                        .orElseThrow( () -> new PwmUnrecoverableException( PwmError.ERROR_NO_CHALLENGES.toInfo() ) );
+                final String userGuid = LdapOperationsHelper.readLdapGuidValue( pwmDomain, null, userIdentity, false );
+                final ResponseInfoBean responseInfoBean = inputData.toResponseInfoBean( PwmConstants.DEFAULT_LOCALE, challengeSet.getIdentifier() );
+                pwmDomain.getCrService().writeResponses( null, userIdentity, user, userGuid, responseInfoBean );
             }
-
-            out( "output complete, " + counter + " responses imported in " + TimeDuration.fromCurrent( startTime ).asCompactString() );
+            catch ( final Exception e )
+            {
+                out( "error writing responses to user '" + user.getEntryDN() + "', error: " + e.getMessage() );
+            }
+        }
+        else
+        {
+            out( "user '" + user.getEntryDN() + "' is not a valid userDN" );
         }
     }
 
-    private PwmDomain figureDomain( final UserIdentity userIdentity, final PwmApplication pwmApplication )
+    private static PwmDomain figureDomain( final UserIdentity userIdentity, final PwmApplication pwmApplication )
     {
         if ( pwmApplication.isMultiDomain() )
         {

+ 21 - 4
server/src/main/java/password/pwm/util/cli/commands/LdapSchemaExtendCommand.java

@@ -21,22 +21,26 @@
 package password.pwm.util.cli.commands;
 
 
+import com.novell.ldapchai.exception.ChaiUnavailableException;
 import com.novell.ldapchai.provider.ChaiConfiguration;
 import com.novell.ldapchai.provider.ChaiProvider;
 import com.novell.ldapchai.provider.ChaiProviderFactory;
 import password.pwm.error.PwmOperationalException;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.ldap.schema.SchemaManager;
 import password.pwm.ldap.schema.SchemaOperationResult;
+import password.pwm.util.cli.CliException;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.java.CollectionUtil;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 import password.pwm.util.secure.PwmTrustManager;
 import password.pwm.util.secure.X509CertInfo;
 import password.pwm.util.secure.X509Utils;
 
 import javax.net.ssl.X509TrustManager;
 import java.io.Console;
+import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.security.cert.X509Certificate;
@@ -52,7 +56,7 @@ public class LdapSchemaExtendCommand extends AbstractCliCommand
 
     @Override
     public void doCommand( )
-            throws Exception
+            throws IOException, CliException
     {
         final String ldapUrl = ( String ) cliEnvironment.getOptions().get( OPTION_LDAPURL );
         final String bindDN = ( String ) cliEnvironment.getOptions().get( OPTION_BIND_DN );
@@ -69,6 +73,19 @@ public class LdapSchemaExtendCommand extends AbstractCliCommand
             bindPW = new String( console.readPassword() );
         }
 
+        try
+        {
+            doSchemaExtension( ldapUrl, bindDN, bindPW );
+        }
+        catch ( final URISyntaxException | PwmOperationalException | ChaiUnavailableException | PwmUnrecoverableException e )
+        {
+            throw new CliException( "error during schema extension: " + e.getMessage(), e );
+        }
+    }
+
+    private void doSchemaExtension( final String ldapUrl, final String bindDN, final String bindPW )
+            throws URISyntaxException, PwmOperationalException, IOException, ChaiUnavailableException, PwmUnrecoverableException
+    {
         final X509TrustManager trustManager;
         if ( isSecureLDAP( ldapUrl ) )
         {
@@ -85,7 +102,7 @@ public class LdapSchemaExtendCommand extends AbstractCliCommand
             trustManager = null;
         }
 
-        if ( !promptForContinue( "Proceeding may cause modificiations to your LDAP schema." ) )
+        if ( !promptForContinue( "Proceeding may cause modifications to your LDAP schema." ) )
         {
             return;
         }
@@ -123,7 +140,7 @@ public class LdapSchemaExtendCommand extends AbstractCliCommand
     }
 
     private List<X509Certificate> readCertificates( final String url )
-            throws URISyntaxException, PwmOperationalException
+            throws URISyntaxException, PwmOperationalException, IOException
     {
         if ( isSecureLDAP( url ) )
         {

+ 4 - 3
server/src/main/java/password/pwm/util/cli/commands/LocalDBInfoCommand.java

@@ -23,20 +23,21 @@ package password.pwm.util.cli.commands;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.java.FileSystemUtility;
 import password.pwm.util.java.MiscUtil;
-import password.pwm.util.json.JsonProvider;
-import password.pwm.util.json.JsonFactory;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.TimeDuration;
+import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 import password.pwm.util.localdb.LocalDB;
 import password.pwm.util.localdb.LocalDBUtility;
 
+import java.io.IOException;
 import java.time.Instant;
 import java.util.Map;
 
 public class LocalDBInfoCommand extends AbstractCliCommand
 {
     @Override
-    public void doCommand( ) throws Exception
+    public void doCommand( ) throws IOException
     {
         final Instant startTime = Instant.now();
         final LocalDB localDB = cliEnvironment.getLocalDB();

+ 3 - 1
server/src/main/java/password/pwm/util/cli/commands/ResetInstanceIDCommand.java

@@ -24,10 +24,12 @@ import password.pwm.AppAttribute;
 import password.pwm.PwmApplication;
 import password.pwm.util.cli.CliParameters;
 
+import java.io.IOException;
+
 public class ResetInstanceIDCommand extends AbstractCliCommand
 {
     @Override
-    public void doCommand( ) throws Exception
+    public void doCommand( ) throws IOException
     {
         final PwmApplication pwmApplication = cliEnvironment.getPwmApplication();
         final String currentInstanceID = pwmApplication.getInstanceID();

+ 26 - 7
server/src/main/java/password/pwm/util/cli/commands/ResponseStatsCommand.java

@@ -35,16 +35,18 @@ import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.ldap.search.SearchConfiguration;
 import password.pwm.ldap.search.UserSearchEngine;
+import password.pwm.svc.cr.CrService;
+import password.pwm.util.cli.CliException;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.java.ConditionalTaskExecutor;
 import password.pwm.util.java.PwmTimeUtil;
-import password.pwm.util.json.JsonProvider;
-import password.pwm.util.json.JsonFactory;
 import password.pwm.util.java.TimeDuration;
-import password.pwm.svc.cr.CrService;
+import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -59,14 +61,21 @@ public class ResponseStatsCommand extends AbstractCliCommand
 
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException, CliException
     {
         final PwmApplication pwmApplication = cliEnvironment.getPwmApplication();
         final ResponseStats responseStats = new ResponseStats();
 
         for ( final PwmDomain pwmDomain : pwmApplication.domains().values() )
         {
-            makeStatistics( pwmDomain, responseStats );
+            try
+            {
+                makeStatistics( pwmDomain, responseStats );
+            }
+            catch ( final PwmUnrecoverableException | ChaiUnavailableException | PwmOperationalException e )
+            {
+                throw new CliException( "error generating response statistics: " + e.getMessage(), e );
+            }
         }
         final File outputFile = ( File ) cliEnvironment.getOptions().get( CliParameters.REQUIRED_NEW_OUTPUT_FILE.getName() );
         final long startTime = System.currentTimeMillis();
@@ -90,7 +99,7 @@ public class ResponseStatsCommand extends AbstractCliCommand
             final PwmDomain pwmDomain,
             final ResponseStats responseStats
     )
-            throws PwmUnrecoverableException, ChaiUnavailableException, PwmOperationalException
+            throws PwmUnrecoverableException, ChaiUnavailableException, PwmOperationalException, IOException
     {
         out( "searching for users in domain " + pwmDomain.getDomainID() );
         final List<UserIdentity> userIdentities = readAllUsersFromLdap( pwmDomain );
@@ -98,7 +107,17 @@ public class ResponseStatsCommand extends AbstractCliCommand
 
 
         final ConditionalTaskExecutor debugOutputter = ConditionalTaskExecutor.forPeriodicTask(
-                () -> out( "processing...  " + userCounter + " users read" ),
+                () ->
+                {
+                    try
+                    {
+                        out( "processing...  " + userCounter + " users read" );
+                    }
+                    catch ( final IOException e )
+                    {
+                        throw new IllegalStateException( "unexpected error writing to log output: " + e.getMessage() );
+                    }
+                },
                 TimeDuration.SECONDS_30.asDuration() );
 
         final CrService crService = pwmDomain.getCrService();

+ 3 - 1
server/src/main/java/password/pwm/util/cli/commands/ShellCommand.java

@@ -26,6 +26,7 @@ import password.pwm.util.cli.CliException;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.cli.MainClass;
 
+import java.io.IOException;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -58,7 +59,7 @@ public class ShellCommand extends AbstractCliCommand
 
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException
     {
         boolean exitFlag = false;
 
@@ -83,6 +84,7 @@ public class ShellCommand extends AbstractCliCommand
     }
 
     final void processCommand( final String commandLine )
+            throws IOException
     {
         if ( commandLine == null )
         {

+ 2 - 1
server/src/main/java/password/pwm/util/cli/commands/TokenInfoCommand.java

@@ -29,6 +29,7 @@ import password.pwm.svc.token.TokenService;
 import password.pwm.util.cli.CliParameters;
 import password.pwm.util.java.StringUtil;
 
+import java.io.IOException;
 import java.util.List;
 
 public class TokenInfoCommand extends AbstractCliCommand
@@ -39,7 +40,7 @@ public class TokenInfoCommand extends AbstractCliCommand
 
     @Override
     public void doCommand( )
-            throws Exception
+            throws IOException
     {
         final String tokenKey = ( String ) cliEnvironment.getOptions().get( TOKEN_KEY_OPTION_TOKEN );
         final String domainId = ( String ) cliEnvironment.getOptions().get( TOKEN_KEY_OPTION_DOMAIN );

+ 1 - 2
server/src/main/java/password/pwm/util/cli/commands/UserReportCommand.java

@@ -45,7 +45,7 @@ public class UserReportCommand extends AbstractCliCommand
     @Override
     @SuppressFBWarnings( "DM_EXIT" )
     void doCommand( )
-            throws Exception
+            throws IOException
     {
         final File outputFile = ( File ) cliEnvironment.getOptions().get( OUTPUT_FILE_OPTIONNAME );
 
@@ -76,7 +76,6 @@ public class UserReportCommand extends AbstractCliCommand
         {
             out( "unable to open file '" + outputFile.getAbsolutePath() + "' for writing" );
             System.exit( -1 );
-            throw new Exception();
         }
 
         out( "report output complete." );

+ 3 - 1
server/src/main/java/password/pwm/util/cli/commands/VersionCommand.java

@@ -23,11 +23,13 @@ package password.pwm.util.cli.commands;
 import password.pwm.PwmConstants;
 import password.pwm.util.cli.CliParameters;
 
+import java.io.IOException;
+
 public class VersionCommand extends AbstractCliCommand
 {
     @Override
     void doCommand( )
-            throws Exception
+            throws IOException
     {
         out( PwmConstants.PWM_APP_NAME + " version " + PwmConstants.SERVLET_VERSION );
     }

+ 4 - 1
server/src/main/java/password/pwm/util/debug/AppItemGenerator.java

@@ -20,6 +20,9 @@
 
 package password.pwm.util.debug;
 
+import password.pwm.error.PwmUnrecoverableException;
+
+import java.io.IOException;
 import java.io.OutputStream;
 
 interface AppItemGenerator
@@ -30,5 +33,5 @@ interface AppItemGenerator
     void outputItem(
             AppDebugItemInput debugItemInput,
             OutputStream outputStream
-    ) throws Exception;
+    ) throws IOException, PwmUnrecoverableException;
 }

+ 2 - 1
server/src/main/java/password/pwm/util/debug/AppPropertiesItemGenerator.java

@@ -26,6 +26,7 @@ import password.pwm.util.java.CollectionUtil;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Map;
 
@@ -39,7 +40,7 @@ class AppPropertiesItemGenerator implements AppItemGenerator
 
     @Override
     public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
-            throws Exception
+            throws IOException
     {
         final AppConfig config = debugItemInput.getObfuscatedAppConfig();
         final Map<AppProperty, String> appPropertyMap = config.readAllAppProperties();

+ 3 - 1
server/src/main/java/password/pwm/util/debug/BuildManifestDebugItemGenerator.java

@@ -24,6 +24,7 @@ import password.pwm.PwmConstants;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 
 class BuildManifestDebugItemGenerator implements AppItemGenerator
@@ -35,7 +36,8 @@ class BuildManifestDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final String json = JsonFactory.get().serializeMap( PwmConstants.BUILD_MANIFEST, JsonProvider.Flag.PrettyPrint );
         DebugItemGenerator.writeString( outputStream, json );

+ 4 - 2
server/src/main/java/password/pwm/util/debug/CacheServiceDebugItemGenerator.java

@@ -23,9 +23,10 @@ package password.pwm.util.debug;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.svc.cache.CacheService;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Serializable;
 import java.util.LinkedHashMap;
@@ -40,7 +41,8 @@ class CacheServiceDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final PwmApplication pwmApplication = debugItemInput.getPwmApplication();
         final CacheService cacheService = pwmApplication.getCacheService();

+ 5 - 2
server/src/main/java/password/pwm/util/debug/ClusterInfoDebugGenerator.java

@@ -22,11 +22,13 @@ package password.pwm.util.debug;
 
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.node.NodeService;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Serializable;
 import java.util.ArrayList;
@@ -42,7 +44,8 @@ class ClusterInfoDebugGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException, PwmUnrecoverableException
     {
         final PwmApplication pwmApplication = debugItemInput.getPwmApplication();
         final NodeService nodeService = pwmApplication.getNodeService();

+ 4 - 2
server/src/main/java/password/pwm/util/debug/ConfigurationDebugJsonItemGenerator.java

@@ -25,9 +25,10 @@ import password.pwm.config.stored.StoredConfigKey;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.value.StoredValue;
 import password.pwm.util.java.CollectionUtil;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.TreeMap;
 
@@ -40,7 +41,8 @@ class ConfigurationDebugJsonItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final StoredConfiguration storedConfiguration = debugItemInput.getObfuscatedAppConfig().getStoredConfiguration();
         final TreeMap<String, Object> outputObject = new TreeMap<>();

+ 3 - 1
server/src/main/java/password/pwm/util/debug/ConfigurationDebugTextItemGenerator.java

@@ -26,6 +26,7 @@ import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.util.java.CollectionUtil;
 import password.pwm.util.java.StringUtil;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Locale;
 
@@ -38,7 +39,8 @@ class ConfigurationDebugTextItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final Locale locale = PwmConstants.DEFAULT_LOCALE;
         final StoredConfiguration storedConfiguration = debugItemInput.getObfuscatedAppConfig().getStoredConfiguration();

+ 4 - 1
server/src/main/java/password/pwm/util/debug/ConfigurationFileItemGenerator.java

@@ -23,8 +23,10 @@ package password.pwm.util.debug;
 import password.pwm.PwmConstants;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationFactory;
+import password.pwm.error.PwmUnrecoverableException;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.OutputStream;
 
 class ConfigurationFileItemGenerator implements AppItemGenerator
@@ -36,7 +38,8 @@ class ConfigurationFileItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException, PwmUnrecoverableException
     {
         final StoredConfiguration storedConfiguration = debugItemInput.getObfuscatedAppConfig().getStoredConfiguration();
 

+ 5 - 2
server/src/main/java/password/pwm/util/debug/DashboardDataDebugItemGenerator.java

@@ -22,11 +22,13 @@ package password.pwm.util.debug;
 
 import password.pwm.PwmConstants;
 import password.pwm.PwmDomain;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.ContextManager;
 import password.pwm.http.servlet.admin.AppDashboardData;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 
 class DashboardDataDebugItemGenerator implements DomainItemGenerator
@@ -38,7 +40,8 @@ class DashboardDataDebugItemGenerator implements DomainItemGenerator
     }
 
     @Override
-    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException, PwmUnrecoverableException
     {
         final PwmDomain pwmDomain = debugItemInput.getPwmDomain();
         final ContextManager contextManager = pwmDomain.getPwmApplication().getPwmEnvironment().getContextManager();

+ 2 - 1
server/src/main/java/password/pwm/util/debug/DebugItemGenerator.java

@@ -28,6 +28,7 @@ import password.pwm.config.AppConfig;
 import password.pwm.config.DomainConfig;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationUtil;
+import password.pwm.error.PwmInternalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.java.DebugOutputBuilder;
 import password.pwm.util.java.JavaHelper;
@@ -225,7 +226,7 @@ public class DebugItemGenerator
         }
         catch ( final IOException e )
         {
-            throw new RuntimeException( "I/O error writing to zipOutputStream: " + e.getMessage() );
+            throw new PwmInternalException( "i/o error writing to zipOutputStream: " + e.getMessage() );
         }
     }
 }

+ 4 - 1
server/src/main/java/password/pwm/util/debug/DomainItemGenerator.java

@@ -20,6 +20,9 @@
 
 package password.pwm.util.debug;
 
+import password.pwm.error.PwmUnrecoverableException;
+
+import java.io.IOException;
 import java.io.OutputStream;
 
 interface DomainItemGenerator
@@ -30,5 +33,5 @@ interface DomainItemGenerator
     void outputItem(
             DomainDebugItemInput debugItemInput,
             OutputStream outputStream
-    ) throws Exception;
+    ) throws IOException, PwmUnrecoverableException;
 }

+ 3 - 1
server/src/main/java/password/pwm/util/debug/FileInfoDebugItemGenerator.java

@@ -28,6 +28,7 @@ import password.pwm.util.java.StringUtil;
 import password.pwm.util.logging.PwmLogger;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -45,7 +46,8 @@ class FileInfoDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final PwmApplication pwmApplication = debugItemInput.getPwmApplication();
         final File applicationPath = pwmApplication.getPwmEnvironment().getApplicationPath();

+ 4 - 2
server/src/main/java/password/pwm/util/debug/HealthDebugItemGenerator.java

@@ -24,9 +24,10 @@ import lombok.Value;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.health.HealthRecord;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.List;
@@ -49,7 +50,8 @@ class HealthDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final Locale locale = PwmConstants.DEFAULT_LOCALE;
         final PwmApplication pwmApplication = debugItemInput.getPwmApplication();

+ 4 - 1
server/src/main/java/password/pwm/util/debug/IntruderDataGenerator.java

@@ -22,11 +22,13 @@ package password.pwm.util.debug;
 
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.svc.intruder.IntruderSystemService;
 import password.pwm.svc.intruder.PublicIntruderRecord;
 import password.pwm.util.java.ClosableIterator;
 import password.pwm.util.json.JsonFactory;
 
+import java.io.IOException;
 import java.io.OutputStream;
 
 class IntruderDataGenerator implements AppItemGenerator
@@ -38,7 +40,8 @@ class IntruderDataGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException, PwmUnrecoverableException
     {
         final PwmApplication pwmApplication = debugItemInput.getPwmApplication();
         final IntruderSystemService service = pwmApplication.getIntruderSystemService();

+ 4 - 1
server/src/main/java/password/pwm/util/debug/LDAPPermissionItemGenerator.java

@@ -22,10 +22,12 @@ package password.pwm.util.debug;
 
 import org.apache.commons.csv.CSVPrinter;
 import password.pwm.config.DomainConfig;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.util.LDAPPermissionCalculator;
 import password.pwm.util.java.MiscUtil;
 import password.pwm.util.java.StringUtil;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.List;
@@ -39,7 +41,8 @@ class LDAPPermissionItemGenerator implements DomainItemGenerator
     }
 
     @Override
-    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException, PwmUnrecoverableException
     {
 
         final DomainConfig domainConfig = debugItemInput.getObfuscatedDomainConfig();

+ 3 - 1
server/src/main/java/password/pwm/util/debug/LdapConnectionsDebugItemGenerator.java

@@ -26,6 +26,7 @@ import password.pwm.ldap.LdapConnectionService;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.List;
 
@@ -38,7 +39,8 @@ class LdapConnectionsDebugItemGenerator implements DomainItemGenerator
     }
 
     @Override
-    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final PwmDomain pwmDomain = debugItemInput.getPwmDomain();
         final List<LdapConnectionService.ConnectionInfo> connectionInfos = pwmDomain.getLdapConnectionService().getConnectionInfos();

+ 3 - 1
server/src/main/java/password/pwm/util/debug/LdapDebugItemGenerator.java

@@ -24,6 +24,7 @@ import password.pwm.ldap.LdapDebugDataGenerator;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.List;
 
@@ -36,7 +37,8 @@ class LdapDebugItemGenerator implements DomainItemGenerator
     }
 
     @Override
-    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final List<LdapDebugDataGenerator.LdapDebugInfo> ldapDebugInfos = LdapDebugDataGenerator.makeLdapDebugInfos(
                 debugItemInput.getPwmDomain(),

+ 5 - 2
server/src/main/java/password/pwm/util/debug/LdapRecentUserDebugGenerator.java

@@ -23,11 +23,13 @@ package password.pwm.util.debug;
 import password.pwm.PwmConstants;
 import password.pwm.PwmDomain;
 import password.pwm.bean.UserIdentity;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.servlet.admin.UserDebugDataBean;
 import password.pwm.http.servlet.admin.UserDebugDataReader;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.List;
@@ -42,7 +44,8 @@ class LdapRecentUserDebugGenerator implements DomainItemGenerator
     }
 
     @Override
-    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final DomainDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException, PwmUnrecoverableException
     {
         final PwmDomain pwmDomain = debugItemInput.getPwmDomain();
         final List<UserIdentity> recentUsers = pwmDomain.getPwmApplication().getSessionTrackService().getRecentLogins();

+ 4 - 2
server/src/main/java/password/pwm/util/debug/LocalDBDebugGenerator.java

@@ -22,10 +22,11 @@ package password.pwm.util.debug;
 
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 import password.pwm.util.localdb.LocalDB;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Serializable;
 import java.util.Map;
@@ -39,7 +40,8 @@ class LocalDBDebugGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final PwmApplication pwmApplication = debugItemInput.getPwmApplication();
         final LocalDB localDB = pwmApplication.getLocalDB();

+ 4 - 2
server/src/main/java/password/pwm/util/debug/LogDebugItemGenerator.java

@@ -32,6 +32,7 @@ import password.pwm.util.logging.PwmLogEvent;
 import password.pwm.util.logging.PwmLogLevel;
 import password.pwm.util.logging.PwmLogger;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.time.Instant;
 import java.util.function.Function;
@@ -45,7 +46,7 @@ class LogDebugItemGenerator implements AppItemGenerator
             final OutputStream outputStream,
             final Function<PwmLogEvent, String> logEventFormatter
     )
-            throws Exception
+            throws IOException
     {
         final long maxByteCount = JavaHelper.silentParseLong( pwmApplication.getConfig().readAppProperty( AppProperty.CONFIG_MANAGER_ZIPDEBUG_MAXLOGBYTES ), 10_000_000 );
         final int maxSeconds = JavaHelper.silentParseInt( pwmApplication.getConfig().readAppProperty( AppProperty.CONFIG_MANAGER_ZIPDEBUG_MAXLOGSECONDS ), 60 );
@@ -74,7 +75,8 @@ class LogDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final Instant startTime = Instant.now();
         final Function<PwmLogEvent, String> logEventFormatter = PwmLogEvent::toLogString;

+ 4 - 2
server/src/main/java/password/pwm/util/debug/LogJsonItemGenerator.java

@@ -20,11 +20,12 @@
 
 package password.pwm.util.debug;
 
-import password.pwm.util.json.JsonFactory;
 import password.pwm.util.java.TimeDuration;
+import password.pwm.util.json.JsonFactory;
 import password.pwm.util.logging.PwmLogEvent;
 import password.pwm.util.logging.PwmLogger;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.time.Instant;
 import java.util.function.Function;
@@ -40,7 +41,8 @@ class LogJsonItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final Instant startTime = Instant.now();
         final Function<PwmLogEvent, String> logEventFormatter = JsonFactory.get()::serialize;

+ 4 - 2
server/src/main/java/password/pwm/util/debug/RootFileSystemDebugItemGenerator.java

@@ -23,10 +23,11 @@ package password.pwm.util.debug;
 import lombok.Builder;
 import lombok.Value;
 import password.pwm.PwmConstants;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Serializable;
 import java.util.Arrays;
@@ -42,7 +43,8 @@ class RootFileSystemDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final Collection<RootFileSystemInfo> rootInfos = RootFileSystemInfo.forAllRootFileSystems();
         outputStream.write( JsonFactory.get().serializeCollection( rootInfos, JsonProvider.Flag.PrettyPrint ).getBytes( PwmConstants.DEFAULT_CHARSET ) );

+ 5 - 2
server/src/main/java/password/pwm/util/debug/ServicesDebugItemGenerator.java

@@ -22,10 +22,12 @@ package password.pwm.util.debug;
 
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.servlet.admin.AppDashboardData;
-import password.pwm.util.json.JsonProvider;
 import password.pwm.util.json.JsonFactory;
+import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.List;
 
@@ -38,7 +40,8 @@ class ServicesDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException, PwmUnrecoverableException
     {
         final PwmApplication pwmApplication = debugItemInput.getPwmApplication();
         final List<AppDashboardData.ServiceData> serviceDataList = AppDashboardData.makeServiceData( pwmApplication );

+ 3 - 1
server/src/main/java/password/pwm/util/debug/SessionDataGenerator.java

@@ -22,6 +22,7 @@ package password.pwm.util.debug;
 
 import password.pwm.PwmApplication;
 
+import java.io.IOException;
 import java.io.OutputStream;
 
 class SessionDataGenerator implements AppItemGenerator
@@ -33,7 +34,8 @@ class SessionDataGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final PwmApplication pwmDomain = debugItemInput.getPwmApplication();
         pwmDomain.getSessionTrackService().outputToCsv( debugItemInput.getLocale(), pwmDomain.getConfig(), outputStream );

+ 3 - 1
server/src/main/java/password/pwm/util/debug/StatisticsDataDebugItemGenerator.java

@@ -23,6 +23,7 @@ package password.pwm.util.debug;
 import password.pwm.PwmApplication;
 import password.pwm.svc.stats.StatisticsService;
 
+import java.io.IOException;
 import java.io.OutputStream;
 
 class StatisticsDataDebugItemGenerator implements AppItemGenerator
@@ -34,7 +35,8 @@ class StatisticsDataDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final PwmApplication pwmApplication = debugItemInput.getPwmApplication();
         final StatisticsService statsManager = pwmApplication.getStatisticsManager();

+ 4 - 1
server/src/main/java/password/pwm/util/debug/StatisticsEpsDataDebugItemGenerator.java

@@ -29,6 +29,7 @@ import password.pwm.util.java.MiscUtil;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.logging.PwmLogger;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.math.BigDecimal;
 import java.util.ArrayList;
@@ -45,7 +46,9 @@ class StatisticsEpsDataDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
+
     {
         final PwmApplication pwmDomain = debugItemInput.getPwmApplication();
         final StatisticsService statsManager = pwmDomain.getStatisticsManager();

+ 3 - 1
server/src/main/java/password/pwm/util/debug/SystemEnvironmentItemGenerator.java

@@ -23,6 +23,7 @@ package password.pwm.util.debug;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.util.json.JsonProvider;
 
+import java.io.IOException;
 import java.io.OutputStream;
 
 class SystemEnvironmentItemGenerator implements AppItemGenerator
@@ -34,7 +35,8 @@ class SystemEnvironmentItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final String json = JsonFactory.get().serializeMap( System.getenv(), JsonProvider.Flag.PrettyPrint );
         DebugItemGenerator.writeString( outputStream, json );

+ 3 - 1
server/src/main/java/password/pwm/util/debug/ThreadDumpDebugItemGenerator.java

@@ -22,6 +22,7 @@ package password.pwm.util.debug;
 
 import password.pwm.util.java.JavaHelper;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.management.ManagementFactory;
 import java.lang.management.ThreadInfo;
@@ -35,7 +36,8 @@ class ThreadDumpDebugItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
+            throws IOException
     {
         final ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true );
         for ( final ThreadInfo threadInfo : threads )

+ 4 - 1
server/src/main/java/password/pwm/util/java/CachingProxyWrapper.java

@@ -20,6 +20,7 @@
 
 package password.pwm.util.java;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import lombok.Value;
 
 import java.lang.reflect.InvocationHandler;
@@ -29,6 +30,7 @@ import java.lang.reflect.Proxy;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+@SuppressFBWarnings( "THROWS_METHOD_THROWS_CLAUSE_THROWABLE" )
 public class CachingProxyWrapper
 {
 
@@ -67,7 +69,8 @@ public class CachingProxyWrapper
         }
 
         @Override
-        public Object invoke( final Object proxy, final Method method, final Object[] args ) throws Throwable
+        public Object invoke( final Object proxy, final Method method, final Object[] args )
+                throws Throwable
         {
 
             final MethodSignature methodSignature = new MethodSignature( method, args );

+ 2 - 0
server/src/main/java/password/pwm/util/java/Memorizer.java

@@ -20,6 +20,7 @@
 
 package password.pwm.util.java;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import lombok.Value;
 
 import java.lang.reflect.InvocationHandler;
@@ -31,6 +32,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+@SuppressFBWarnings( "THROWS_METHOD_THROWS_CLAUSE_THROWABLE" )
 public class Memorizer implements InvocationHandler
 {
     private final StatisticCounterBundle<DebugStats> stats = new StatisticCounterBundle<>( DebugStats.class );

+ 2 - 2
server/src/main/java/password/pwm/util/json/MoshiJsonServiceProvider.java

@@ -143,7 +143,7 @@ class MoshiJsonServiceProvider implements JsonProvider
         }
         catch ( final IOException e )
         {
-            throw new RuntimeException( e.getMessage(), e );
+            throw new IllegalStateException( e.getMessage(), e );
         }
     }
 
@@ -154,7 +154,7 @@ class MoshiJsonServiceProvider implements JsonProvider
         return jsonAdapter.toJson( object );
     }
 
-    static Class unknownClassResolver( final Object srcObject )
+    static Class<?> unknownClassResolver( final Object srcObject )
     {
         if ( srcObject instanceof List )
         {

+ 0 - 1
server/src/main/java/password/pwm/util/logging/PwmLogEvent.java

@@ -67,7 +67,6 @@ public class PwmLogEvent implements Serializable, Comparable<PwmLogEvent>
 
 
     public static PwmLogEvent fromEncodedString( final String encodedString )
-            throws ClassNotFoundException, IOException
     {
         return JsonFactory.get().deserialize( encodedString, PwmLogEvent.class );
     }

+ 25 - 8
server/src/main/java/password/pwm/util/secure/self/SelfCertFactory.java

@@ -23,6 +23,7 @@ package password.pwm.util.secure.self;
 import password.pwm.AppAttribute;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
+import password.pwm.error.PwmError;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.svc.secure.SystemSecureService;
 import password.pwm.util.PasswordData;
@@ -50,7 +51,7 @@ public class SelfCertFactory
             final PasswordData password,
             final String alias
     )
-        throws Exception
+            throws PwmUnrecoverableException
     {
         final SelfCertSettings settings = SelfCertSettings.fromConfiguration( pwmApplication.getConfig() );
 
@@ -59,7 +60,15 @@ public class SelfCertFactory
         {
             if ( evaluateExistingStoredCert( existingCert.get(), settings ) )
             {
-                return storedCertToKeyStore( existingCert.get(), alias, password );
+                try
+                {
+                    return storedCertToKeyStore( existingCert.get(), alias, password );
+                }
+                catch ( final Exception e )
+                {
+                    final String errorMsg = "error reading existing stored certificate: " + e.getMessage();
+                    throw PwmUnrecoverableException.newException( PwmError.ERROR_CERTIFICATE_ERROR, errorMsg  );
+                }
             }
         }
 
@@ -76,13 +85,21 @@ public class SelfCertFactory
         final PasswordData password,
         final String alias
     )
-        throws Exception
+            throws PwmUnrecoverableException
     {
-        final SelfCertGenerator selfCertGenerator = new SelfCertGenerator(
-                settings,
-                domainSecureService == null ? PwmRandom.getInstance() : domainSecureService.pwmRandom() );
-        final StoredCertData storedCertData = selfCertGenerator.generateNewCertificate( makeSubjectName( settings ) );
-        return storedCertToKeyStore( storedCertData, alias, password );
+        try
+        {
+            final SelfCertGenerator selfCertGenerator = new SelfCertGenerator(
+                    settings,
+                    domainSecureService == null ? PwmRandom.getInstance() : domainSecureService.pwmRandom() );
+            final StoredCertData storedCertData = selfCertGenerator.generateNewCertificate( makeSubjectName( settings ) );
+            return storedCertToKeyStore( storedCertData, alias, password );
+        }
+        catch ( final Exception e )
+        {
+            final String errorMsg = "error generating new certificate: " + e.getMessage();
+            throw PwmUnrecoverableException.newException( PwmError.ERROR_CERTIFICATE_ERROR, errorMsg  );
+        }
     }
 
     private static Optional<StoredCertData> loadExistingStoredCert( final PwmApplication pwmApplication )