From b5f86cb0fca1d6feb52a7906a8394c8537aeedea Mon Sep 17 00:00:00 2001
From: Rick Herrick <jrherrick@wustl.edu>
Date: Tue, 1 Nov 2016 03:33:06 -0500
Subject: [PATCH] XNAT-4557 XNAT-4558 Added support for preference aliases.
 Moved notification preference change handling to SmtpHandlerMethod.

---
 build.gradle                                  |   2 +-
 .../dcm/id/ClassicDicomObjectIdentifier.java  |  36 +-
 .../nrg/pipeline/XnatPipelineLauncher.java    |  20 +-
 .../java/org/nrg/viewer/QCImageCreator.java   |   2 +-
 .../InsufficientPrivilegesException.java      |  25 ++
 .../xapi/rest/XapiRestControllerAdvice.java   |  12 +
 .../rest/notifications/NotificationsApi.java  | 385 ++++++++----------
 .../nrg/xapi/rest/settings/SiteConfigApi.java |  56 ++-
 .../org/nrg/xapi/rest/users/UsersApi.java     |  16 +-
 .../java/org/nrg/xnat/archive/Transfer.java   |   2 +-
 .../configuration/NotificationsConfig.java    |  22 +-
 .../xnat/configuration/PreferencesConfig.java |  27 --
 .../xnat/configuration/SchedulerConfig.java   |   6 +-
 .../SiteConfigPreferenceHandler.java          |  60 ++-
 .../methods/FeatureServicesHandlerMethod.java |   5 +-
 .../methods/InitializedHandlerMethod.java     | 106 +++++
 .../methods/RequiredChannelHandlerMethod.java |   2 +-
 .../methods/RoleServicesHandlerMethod.java    |   2 +-
 .../listeners/methods/SmtpHandlerMethod.java  |  66 ++-
 ...atUserProviderPreferenceHandlerMethod.java |  52 +++
 .../xnat/helpers/prearchive/PrearcUtils.java  |  45 +-
 .../restlet/actions/TriggerPipelines.java     |   2 +-
 .../resources/ProjtExptPipelineResource.java  |   4 +-
 .../modules/actions/ManagePipeline.java       |   2 +-
 .../modules/actions/PipelineActions.java      |   2 +-
 .../turbine/modules/actions/QDECAction.java   |   2 +-
 .../xnat/turbine/utils/ArcSpecManager.java    |  17 +-
 .../org/nrg/xnat/utils/XnatUserProvider.java  |  28 +-
 .../xnat/preferences/site-config.properties   |  62 ---
 .../xnat/spawner/site-admin-elements.yaml     |  53 ++-
 .../webapp/WEB-INF/conf/services.properties   |  91 -----
 .../webapp/resources/samples/prefs-init.ini   |  30 ++
 .../samples}/xnat-conf.properties             |   0
 .../webapp/scripts/project/settingsTabMgmt.js |   4 +-
 src/main/webapp/setup/site-setup.yaml         |  18 +-
 .../webapp/xdat-templates/layouts/Default.vm  |   2 +-
 .../xdat-templates/macros/TurbineMacros.vm    |   8 +-
 .../webapp/xnat-templates/layouts/Index.vm    |   2 +-
 .../navigations/HeaderIncludes.vm             |  10 +-
 .../navigations/XNATQuickSearch.vm            |   2 +-
 .../screens/xnat_ctSessionData/edit/scans.vm  |   4 +-
 .../actionsBox/ManageFiles.vm                 |   2 +-
 .../xnat_imageSessionData/edit/scans.vm       |   4 +-
 .../screens/xnat_mrSessionData/edit/scans.vm  |   4 +-
 .../screens/xnat_petSessionData/edit/scans.vm |   4 +-
 .../xnat_petmrSessionData/edit/scans.vm       |   2 +-
 .../actionsBox/ManageFiles.vm                 |   2 +-
 .../xnat_subjectData_assessor.vm              |   4 +-
 48 files changed, 659 insertions(+), 655 deletions(-)
 create mode 100644 src/main/java/org/nrg/xapi/exceptions/InsufficientPrivilegesException.java
 create mode 100644 src/main/java/org/nrg/xnat/event/listeners/methods/InitializedHandlerMethod.java
 create mode 100644 src/main/java/org/nrg/xnat/event/listeners/methods/XnatUserProviderPreferenceHandlerMethod.java
 delete mode 100644 src/main/resources/META-INF/xnat/preferences/site-config.properties
 delete mode 100644 src/main/webapp/WEB-INF/conf/services.properties
 create mode 100644 src/main/webapp/resources/samples/prefs-init.ini
 rename src/main/webapp/{WEB-INF/conf => resources/samples}/xnat-conf.properties (100%)

diff --git a/build.gradle b/build.gradle
index 59c17d7f..9543b208 100644
--- a/build.gradle
+++ b/build.gradle
@@ -465,7 +465,7 @@ dependencies {
     runtime "org.codehaus.groovy.modules.http-builder:http-builder:0.7.2"
     runtime "net.imagej:ij:1.50e"
     runtime "net.bull.javamelody:javamelody-core:1.58.0"
-    runtime "org.javassist:javassist:3.20.0-GA"
+    runtime "org.javassist:javassist:3.21.0-GA"
 
     providedCompile "javax.servlet:javax.servlet-api:${vServletApi}"
 
diff --git a/src/main/java/org/nrg/dcm/id/ClassicDicomObjectIdentifier.java b/src/main/java/org/nrg/dcm/id/ClassicDicomObjectIdentifier.java
index 628f3aa0..34b19420 100644
--- a/src/main/java/org/nrg/dcm/id/ClassicDicomObjectIdentifier.java
+++ b/src/main/java/org/nrg/dcm/id/ClassicDicomObjectIdentifier.java
@@ -19,31 +19,19 @@ import java.util.List;
 import java.util.regex.Pattern;
 
 public class ClassicDicomObjectIdentifier extends CompositeDicomObjectIdentifier {
-    private static final ImmutableList<Extractor> aaExtractors, sessionExtractors, subjectExtractors;
-    static {
-        final ImmutableList.Builder<Extractor> aab = new ImmutableList.Builder<Extractor>();
-        aab.add(new ContainedAssignmentExtractor(Tag.PatientComments, "AA", Pattern.CASE_INSENSITIVE),
-                new ContainedAssignmentExtractor(Tag.StudyComments, "AA", Pattern.CASE_INSENSITIVE));
-        aaExtractors = aab.build();
-
-        final ImmutableList.Builder<Extractor> sessb = new ImmutableList.Builder<Extractor>();
-        sessb.add(new ContainedAssignmentExtractor(Tag.PatientComments, "Session", Pattern.CASE_INSENSITIVE),
-                new ContainedAssignmentExtractor(Tag.StudyComments, "Session", Pattern.CASE_INSENSITIVE),
-                new TextExtractor(Tag.PatientID));
-        sessionExtractors = sessb.build();
-
-        final ImmutableList.Builder<Extractor> subjb = new ImmutableList.Builder<Extractor>();
-        subjb.add(new ContainedAssignmentExtractor(Tag.PatientComments, "Subject", Pattern.CASE_INSENSITIVE),
-                new ContainedAssignmentExtractor(Tag.StudyComments, "Subject", Pattern.CASE_INSENSITIVE),
-                new TextExtractor(Tag.PatientName));
-        subjectExtractors = subjb.build();
-    }
-
-    public static List<Extractor> getAAExtractors() { return aaExtractors; }
-    public static List<Extractor> getSessionExtractors() { return sessionExtractors; }
-    public static List<Extractor> getSubjectExtractors() { return subjectExtractors; }
+    private static final ImmutableList<Extractor> attributeExtractors = new ImmutableList.Builder<Extractor>().add(new ContainedAssignmentExtractor(Tag.PatientComments, "AA", Pattern.CASE_INSENSITIVE))
+                                                                                                              .add(new ContainedAssignmentExtractor(Tag.StudyComments, "AA", Pattern.CASE_INSENSITIVE))
+                                                                                                              .build();
+    private static final ImmutableList<Extractor> sessionExtractors   = new ImmutableList.Builder<Extractor>().add(new ContainedAssignmentExtractor(Tag.PatientComments, "Session", Pattern.CASE_INSENSITIVE))
+                                                                                                              .add(new ContainedAssignmentExtractor(Tag.StudyComments, "Session", Pattern.CASE_INSENSITIVE))
+                                                                                                              .add(new TextExtractor(Tag.PatientID))
+                                                                                                              .build();
+    private static final ImmutableList<Extractor> subjectExtractors   = new ImmutableList.Builder<Extractor>().add(new ContainedAssignmentExtractor(Tag.PatientComments, "Subject", Pattern.CASE_INSENSITIVE))
+                                                                                                              .add(new ContainedAssignmentExtractor(Tag.StudyComments, "Subject", Pattern.CASE_INSENSITIVE))
+                                                                                                              .add(new TextExtractor(Tag.PatientName))
+                                                                                                              .build();
 
     public ClassicDicomObjectIdentifier() {
-        super(new Xnat15DicomProjectIdentifier(), subjectExtractors, sessionExtractors, aaExtractors);
+        super(new Xnat15DicomProjectIdentifier(), subjectExtractors, sessionExtractors, attributeExtractors);
     }
 }
diff --git a/src/main/java/org/nrg/pipeline/XnatPipelineLauncher.java b/src/main/java/org/nrg/pipeline/XnatPipelineLauncher.java
index 61e6b935..cea37377 100644
--- a/src/main/java/org/nrg/pipeline/XnatPipelineLauncher.java
+++ b/src/main/java/org/nrg/pipeline/XnatPipelineLauncher.java
@@ -621,7 +621,7 @@ public class XnatPipelineLauncher {
         xnatPipelineLauncher.setParameter("useremail", user.getEmail());
         xnatPipelineLauncher.setParameter("userfullname", XnatPipelineLauncher.getUserName(user));
         xnatPipelineLauncher.setParameter("adminemail", XDAT.getSiteConfigPreferences().getAdminEmail());
-        xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
+        xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().getHostname());
         xnatPipelineLauncher.setParameter("xnatserver", TurbineUtils.GetSystemName());
 
         xnatPipelineLauncher.setId(imageSession.getId());
@@ -651,24 +651,6 @@ public class XnatPipelineLauncher {
         return xnatPipelineLauncher;
     }
 
-    public static XnatPipelineLauncher GetBareLauncherForExperiment(RunData data, Context context, XnatExperimentdata imageSession) throws Exception {
-        XnatPipelineLauncher xnatPipelineLauncher = new XnatPipelineLauncher(data, context);
-        xnatPipelineLauncher.setSupressNotification(true);
-        UserI user = XDAT.getUserDetails();
-        xnatPipelineLauncher.setParameter("useremail", user.getEmail());
-        xnatPipelineLauncher.setParameter("userfullname", XnatPipelineLauncher.getUserName(user));
-        xnatPipelineLauncher.setParameter("adminemail", XDAT.getSiteConfigPreferences().getAdminEmail());
-        xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
-        xnatPipelineLauncher.setParameter("xnatserver", TurbineUtils.GetSystemName());
-
-        xnatPipelineLauncher.setId(imageSession.getId());
-        xnatPipelineLauncher.setLabel(imageSession.getLabel());
-        xnatPipelineLauncher.setDataType(imageSession.getXSIType());
-        xnatPipelineLauncher.setExternalId(imageSession.getProject());
-
-        return xnatPipelineLauncher;
-    }
-
     public static XnatPipelineLauncher GetLauncher(RunData data, Context context, XnatImagesessiondata imageSession) throws Exception {
         XnatPipelineLauncher xnatPipelineLauncher = GetLauncherForExperiment(data, context, imageSession);
         String path = imageSession.getArchivePath();
diff --git a/src/main/java/org/nrg/viewer/QCImageCreator.java b/src/main/java/org/nrg/viewer/QCImageCreator.java
index fc1fbec6..5e252b89 100644
--- a/src/main/java/org/nrg/viewer/QCImageCreator.java
+++ b/src/main/java/org/nrg/viewer/QCImageCreator.java
@@ -49,7 +49,7 @@ public class QCImageCreator {
         xnatPipelineLauncher.setParameter("session", mrSession.getId() );
         xnatPipelineLauncher.setParameter("notify", "0" );
 	    xnatPipelineLauncher.setParameter("xnatserver", TurbineUtils.GetSystemName());
-	    xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
+	    xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().getHostname());
 	    xnatPipelineLauncher.setParameter("useremail", user.getEmail());
 	    xnatPipelineLauncher.setParameter("adminemail", XDAT.getSiteConfigPreferences().getAdminEmail());
 
diff --git a/src/main/java/org/nrg/xapi/exceptions/InsufficientPrivilegesException.java b/src/main/java/org/nrg/xapi/exceptions/InsufficientPrivilegesException.java
new file mode 100644
index 00000000..83f82fac
--- /dev/null
+++ b/src/main/java/org/nrg/xapi/exceptions/InsufficientPrivilegesException.java
@@ -0,0 +1,25 @@
+/*
+ * web: org.nrg.xapi.exceptions.DataFormatException
+ * XNAT http://www.xnat.org
+ * Copyright (c) 2016, Washington University School of Medicine and Howard Hughes Medical Institute
+ * All Rights Reserved
+ *
+ * Released under the Simplified BSD.
+ */
+
+package org.nrg.xapi.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(HttpStatus.BAD_REQUEST)
+public class InsufficientPrivilegesException extends ApiException {
+    public InsufficientPrivilegesException(final String username) {
+        super(HttpStatus.BAD_REQUEST.value(), username);
+    }
+
+    @Override
+    public String getMessage() {
+        return String.format("The user %s has insufficient privileges for the requested operation.", super.getMessage());
+    }
+}
diff --git a/src/main/java/org/nrg/xapi/rest/XapiRestControllerAdvice.java b/src/main/java/org/nrg/xapi/rest/XapiRestControllerAdvice.java
index 9e59bd1b..14a04d5e 100644
--- a/src/main/java/org/nrg/xapi/rest/XapiRestControllerAdvice.java
+++ b/src/main/java/org/nrg/xapi/rest/XapiRestControllerAdvice.java
@@ -17,6 +17,8 @@ import org.nrg.framework.exceptions.NrgServiceError;
 import org.nrg.framework.exceptions.NrgServiceException;
 import org.nrg.framework.exceptions.NrgServiceRuntimeException;
 import org.nrg.xapi.exceptions.DataFormatException;
+import org.nrg.xapi.exceptions.InsufficientPrivilegesException;
+import org.nrg.xapi.exceptions.NotFoundException;
 import org.nrg.xapi.exceptions.ResourceAlreadyExistsException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -45,6 +47,11 @@ public class XapiRestControllerAdvice {
         return handleException(request, exception.getMessage(), exception);
     }
 
+    @ExceptionHandler(InsufficientPrivilegesException.class)
+    public ModelAndView handleInsufficientPrivilegesException(final HttpServletRequest request, final DataFormatException exception) {
+        return handleException(request, exception.getMessage(), exception);
+    }
+
     @ExceptionHandler(ResourceAlreadyExistsException.class)
     public ModelAndView handleDataFormatException(final HttpServletRequest request, final ResourceAlreadyExistsException exception) {
         return handleException(request, exception.getMessage(), exception);
@@ -66,6 +73,11 @@ public class XapiRestControllerAdvice {
         return handleException(HttpStatus.BAD_REQUEST, request, "Unable to find requested file or resource: " + exception.getMessage(), exception);
     }
 
+    @ExceptionHandler(NotFoundException.class)
+    public ModelAndView handleNotFoundException(final HttpServletRequest request, final NotFoundException exception) {
+        return handleException(HttpStatus.BAD_REQUEST, request, exception.getMessage(), exception);
+    }
+
     @ExceptionHandler(ConfigServiceException.class)
     public ModelAndView handleConfigServiceException(final HttpServletRequest request, final ConfigServiceException exception) {
         return handleException(HttpStatus.INTERNAL_SERVER_ERROR, request, "An error occurred when accessing the configuration service: " + exception.getMessage(), exception);
diff --git a/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java b/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java
index 8e4577e3..a748afe9 100644
--- a/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java
+++ b/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java
@@ -12,12 +12,11 @@ package org.nrg.xapi.rest.notifications;
 import io.swagger.annotations.*;
 import org.apache.commons.lang3.StringUtils;
 import org.nrg.framework.annotations.XapiRestController;
-import org.nrg.framework.exceptions.NrgServiceError;
-import org.nrg.framework.exceptions.NrgServiceRuntimeException;
 import org.nrg.framework.services.SerializerService;
 import org.nrg.prefs.exceptions.InvalidPreferenceName;
 import org.nrg.xapi.exceptions.InitializationException;
 import org.nrg.xdat.preferences.NotificationsPreferences;
+import org.nrg.xdat.preferences.SmtpServer;
 import org.nrg.xdat.rest.AbstractXapiRestController;
 import org.nrg.xdat.security.services.RoleHolder;
 import org.nrg.xdat.security.services.UserManagementServiceI;
@@ -28,7 +27,6 @@ import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
-import org.springframework.mail.javamail.JavaMailSenderImpl;
 import org.springframework.web.bind.annotation.*;
 
 import javax.inject.Inject;
@@ -58,10 +56,9 @@ public class NotificationsApi extends AbstractXapiRestController {
                                                        + "by calling the POST version of this method.";
 
     @Inject
-    public NotificationsApi(final UserManagementServiceI userManagementService, final RoleHolder roleHolder, final NotificationsPreferences notificationsPrefs, final JavaMailSenderImpl javaMailSender, final XnatAppInfo appInfo, final SerializerService serializer) {
+    public NotificationsApi(final UserManagementServiceI userManagementService, final RoleHolder roleHolder, final NotificationsPreferences notificationsPrefs, final XnatAppInfo appInfo, final SerializerService serializer) {
         super(userManagementService, roleHolder);
         _notificationsPrefs = notificationsPrefs;
-        _javaMailSender = javaMailSender;
         _appInfo = appInfo;
         _serializer = serializer;
     }
@@ -124,7 +121,7 @@ public class NotificationsApi extends AbstractXapiRestController {
                 } else if (StringUtils.equals(name, "emailRecipientUpdate")) {
                     _notificationsPrefs.setEmailRecipientUpdate(properties.getProperty(name));
                 } else if (StringUtils.equals(name, "smtpServer")) {
-                    _notificationsPrefs.setSmtpServer(_serializer.deserializeJson(properties.getProperty(name), SerializerService.TYPE_REF_MAP_STRING_STRING));
+                    _notificationsPrefs.setSmtpServer(_serializer.deserializeJson(properties.getProperty(name), SmtpServer.class));
                 } else {
                     _notificationsPrefs.set(properties.getProperty(name), name);
                 }
@@ -137,32 +134,12 @@ public class NotificationsApi extends AbstractXapiRestController {
                 _log.error("An error occurred deserializing the preference: " + name + ", which is just lame.");
             }
         }
-
-        // If any of the SMTP properties changed, then change the values for
-        if (properties.containsKey("smtpServer") || properties.containsKey("host") || properties.containsKey("port") || properties.containsKey("protocol") || properties.containsKey("username") || properties.containsKey("password")) {
-            final String host     = _notificationsPrefs.getHostname();
-            final int    port     = _notificationsPrefs.getPort();
-            final String protocol = _notificationsPrefs.getProtocol();
-            final String username = _notificationsPrefs.getUsername();
-            final String password = _notificationsPrefs.getPassword();
-
-            logConfigurationSubmit(host, port, protocol, username, password, properties);
-
-            setHost(host, false);
-            setPort(port);
-            setProtocol(protocol);
-            setUsername(username);
-            setPassword(password);
-
-            _javaMailSender.setJavaMailProperties(getSubmittedProperties(properties));
-        }
-
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
     @ApiOperation(value = "Returns the full SMTP server configuration.",
-                  notes = "Returns the configuration as a map of the standard Java mail sender properties&ndash;host, port, protocol, username, and password&ndash;along with any extended properties required for the configuration, e.g. configuring SSL- or TLS-secured SMTP services.",
-                  response = Properties.class)
+            notes = "Returns the configuration as a map of the standard Java mail sender properties&ndash;host, port, protocol, username, and password&ndash;along with any extended properties required for the configuration, e.g. configuring SSL- or TLS-secured SMTP services.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "SMTP service configuration properties successfully retrieved."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."),
@@ -176,39 +153,18 @@ public class NotificationsApi extends AbstractXapiRestController {
         if (_log.isDebugEnabled()) {
             _log.debug("User " + getSessionUser().getUsername() + " requested the site SMTP service configuration.");
         }
-        final Properties properties = new Properties();
-        properties.setProperty("host", _javaMailSender.getHost());
-        final int port = _javaMailSender.getPort();
-        if (port > 0) {
-            properties.setProperty("port", Integer.toString(port));
-        }
-        final String protocol = _javaMailSender.getProtocol();
-        if (StringUtils.isNotBlank(protocol)) {
-            properties.setProperty("protocol", protocol);
-        }
-        final String username = _javaMailSender.getUsername();
-        if (StringUtils.isNotBlank(username)) {
-            properties.setProperty("username", username);
-        }
-        final String password = _javaMailSender.getPassword();
-        if (StringUtils.isNotBlank(password)) {
-            properties.setProperty("password", password);
-        }
-        for (final String property : _javaMailSender.getJavaMailProperties().stringPropertyNames()) {
-            properties.setProperty(property, _javaMailSender.getJavaMailProperties().getProperty(property));
-        }
-        return new ResponseEntity<>(properties, HttpStatus.OK);
+        return new ResponseEntity<>(_notificationsPrefs.getSmtpServer().asProperties(), HttpStatus.OK);
     }
 
     @ApiOperation(value = "Sets the mail service properties. This return the SMTP server configuration as it exists after being set.",
-                  notes = POST_PROPERTIES_NOTES,
-                  response = Properties.class)
+            notes = POST_PROPERTIES_NOTES,
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service properties successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the mail service properties."),
                    @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = {"smtp"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.POST})
-    public ResponseEntity<Properties> setAllMailProperties(@ApiParam("The value to set for the email host.") @RequestParam(value = "host", required = false, defaultValue = NOT_SET) final String host,
+    public ResponseEntity<Properties> setAllMailProperties(@ApiParam("The value to set for the email host.") @RequestParam(value = "hostname", required = false, defaultValue = NOT_SET) final String hostname,
                                                            @ApiParam("The value to set for the email port.") @RequestParam(value = "port", required = false, defaultValue = "-1") final int port,
                                                            @ApiParam("The value to set for the email username.") @RequestParam(value = "username", required = false, defaultValue = NOT_SET) final String username,
                                                            @ApiParam("The value to set for the email password.") @RequestParam(value = "password", required = false, defaultValue = NOT_SET) final String password,
@@ -220,28 +176,22 @@ public class NotificationsApi extends AbstractXapiRestController {
         }
 
         cleanProperties(properties);
-        logConfigurationSubmit(host, port, username, password, protocol, properties);
+        logConfigurationSubmit(hostname, port, username, password, protocol, properties);
 
-        setHost(host, true);
-        setPort(port);
-        setProtocol(protocol);
-        setUsername(username);
-        setPassword(password);
-
-        _javaMailSender.setJavaMailProperties(getSubmittedProperties(properties));
+        _notificationsPrefs.setSmtpServer(new SmtpServer(hostname, port, protocol, username, password, properties));
 
         return getSmtpServerProperties();
     }
 
     @ApiOperation(value = "Sets the submitted mail service properties. This returns the SMTP server configuration as it exists after being set.",
-                  notes = PUT_PROPERTIES_NOTES,
-                  response = Properties.class)
+            notes = PUT_PROPERTIES_NOTES,
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service properties successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the mail service properties."),
                    @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = {"smtp"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT})
-    public ResponseEntity<Properties> setSubmittedMailProperties(@ApiParam("The value to set for the email host.") @RequestParam(value = "host", required = false, defaultValue = NOT_SET) final String host,
+    public ResponseEntity<Properties> setSubmittedMailProperties(@ApiParam("The value to set for the email host.") @RequestParam(value = "hostname", required = false, defaultValue = NOT_SET) final String host,
                                                                  @ApiParam("The value to set for the email port.") @RequestParam(value = "port", required = false, defaultValue = "-1") final int port,
                                                                  @ApiParam("The value to set for the email username.") @RequestParam(value = "username", required = false, defaultValue = NOT_SET) final String username,
                                                                  @ApiParam("The value to set for the email password.") @RequestParam(value = "password", required = false, defaultValue = NOT_SET) final String password,
@@ -254,23 +204,14 @@ public class NotificationsApi extends AbstractXapiRestController {
 
         logConfigurationSubmit(host, port, username, password, protocol, properties);
 
-        setHost(host, false);
-        setPort(port);
-        setProtocol(protocol);
-        setUsername(username);
-        setPassword(password);
-        if (properties != null) {
-            for (final String property : properties.stringPropertyNames()) {
-                _javaMailSender.getJavaMailProperties().setProperty(property, properties.getProperty(property));
-            }
-        }
+        _notificationsPrefs.setSmtpServer(new SmtpServer(host, port, username, password, protocol, properties));
 
         return getSmtpServerProperties();
     }
 
     @ApiOperation(value = "Sets the mail service host.",
-                  notes = "Sets the mail service host.",
-                  response = Properties.class)
+            notes = "Sets the mail service host.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service host successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the mail service host."),
@@ -284,13 +225,13 @@ public class NotificationsApi extends AbstractXapiRestController {
         if (_log.isInfoEnabled()) {
             _log.info("User " + getSessionUser().getLogin() + " setting mail host to: " + host);
         }
-        setHost(host, true);
+        _notificationsPrefs.setSmtpHostname(host);
         return getSmtpServerProperties();
     }
 
     @ApiOperation(value = "Sets the mail service port.",
-                  notes = "Sets the mail service port.",
-                  response = Properties.class)
+            notes = "Sets the mail service port.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service port successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the mail service port."),
@@ -304,13 +245,13 @@ public class NotificationsApi extends AbstractXapiRestController {
         if (_log.isInfoEnabled()) {
             _log.info("User " + getSessionUser().getLogin() + " setting mail port to: " + port);
         }
-        setPort(port);
+        _notificationsPrefs.setSmtpPort(port);
         return getSmtpServerProperties();
     }
 
     @ApiOperation(value = "Sets the mail service protocol.",
-                  notes = "Sets the mail service protocol.",
-                  response = Properties.class)
+            notes = "Sets the mail service protocol.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service protocol successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the mail service protocol."),
@@ -324,13 +265,13 @@ public class NotificationsApi extends AbstractXapiRestController {
         if (_log.isInfoEnabled()) {
             _log.info("User " + getSessionUser().getLogin() + " setting mail protocol to: " + protocol);
         }
-        setProtocol(protocol);
+        _notificationsPrefs.setSmtpProtocol(protocol);
         return getSmtpServerProperties();
     }
 
     @ApiOperation(value = "Sets the mail service username.",
-                  notes = "Sets the mail service username.",
-                  response = Properties.class)
+            notes = "Sets the mail service username.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service username successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the mail service username."),
@@ -344,13 +285,13 @@ public class NotificationsApi extends AbstractXapiRestController {
         if (_log.isInfoEnabled()) {
             _log.info("User " + getSessionUser().getLogin() + " setting mail username to: " + username);
         }
-        setUsername(username);
+        _notificationsPrefs.setSmtpUsername(username);
         return getSmtpServerProperties();
     }
 
     @ApiOperation(value = "Sets the mail service password.",
-                  notes = "Sets the mail service password.",
-                  response = Properties.class)
+            notes = "Sets the mail service password.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service password successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the mail service password."),
@@ -364,20 +305,56 @@ public class NotificationsApi extends AbstractXapiRestController {
         if (_log.isInfoEnabled()) {
             _log.info("User " + getSessionUser().getLogin() + " setting mail password to: ********");
         }
-        setPassword(password);
+        _notificationsPrefs.setSmtpPassword(password);
         return getSmtpServerProperties();
     }
 
+    @ApiOperation(value = "Gets the value for a specified Java mail property.",
+            notes = "The value is always returned as a string.",
+            response = String.class)
+    @ApiResponses({@ApiResponse(code = 200, message = "Property found and returned."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 403, message = "Not authorized to set the mail service properties."),
+                   @ApiResponse(code = 404, message = "Specified key not found in the mail service properties."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
+    @RequestMapping(value = {"smtp/property/{property}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.GET})
+    public ResponseEntity<String> getExtendedProperty(@ApiParam(value = "The mail property to be retrieved.", required = true) @PathVariable final String property) {
+        final HttpStatus status = isPermitted();
+        if (status != null) {
+            return new ResponseEntity<>(status);
+        }
+        if (!_notificationsPrefs.getSmtpServer().getMailProperties().containsKey(property)) {
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+        }
+        _log.info("User {} retrieving value for property {}", getSessionUser().getLogin(), property);
+        return new ResponseEntity<>(_notificationsPrefs.getSmtpMailProperty(property), HttpStatus.OK);
+    }
+
     @ApiOperation(value = "Sets a Java mail property with the submitted name and value.",
-                  notes = "Setting a property to an empty value will remove the property.",
-                  response = Properties.class)
+            notes = "Setting a property to an existing value will overwrite the existing value. The value returned by this function contains the previous value (if any).",
+            response = String.class)
+    @ApiResponses({@ApiResponse(code = 200, message = "Property found and returned."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 403, message = "Not authorized to set the mail service properties."),
+                   @ApiResponse(code = 404, message = "Specified key not found in the mail service properties."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
+    @RequestMapping(value = {"smtp/property/{property}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT})
+    public ResponseEntity<String> setExtendedProperty(@ApiParam(value = "The name of the extended mail property to set.", required = true) @PathVariable final String property,
+                                                      @ApiParam(value = "The value to set for the extended mail property.", required = true) @RequestBody final String value) {
+        return setExtendedPropertyFromPath(property, value);
+    }
+
+    @ApiOperation(value = "Sets a Java mail property with the submitted name and value.",
+            notes = "Setting a property to an existing value will overwrite the existing value. The value returned by this function contains the previous value (if any).",
+            response = String.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service password successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the mail service password."),
+                   @ApiResponse(code = 404, message = "Specified key not found in the mail service properties."),
                    @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = {"smtp/property/{property}/{value}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT})
-    public ResponseEntity<Properties> setExtendedProperty(@ApiParam(value = "The value to set for the email password.", required = true) @PathVariable final String property,
-                                                          @ApiParam(value = "The value to set for the email password.", required = true) @PathVariable final String value) {
+    public ResponseEntity<String> setExtendedPropertyFromPath(@ApiParam(value = "The name of the extended mail property to set.", required = true) @PathVariable final String property,
+                                                              @ApiParam(value = "The value to set for the extended mail property.", required = true) @PathVariable final String value) {
         final HttpStatus status = isPermitted();
         if (status != null) {
             return new ResponseEntity<>(status);
@@ -385,13 +362,33 @@ public class NotificationsApi extends AbstractXapiRestController {
         if (_log.isInfoEnabled()) {
             _log.info("User " + getSessionUser().getLogin() + " setting mail password to: ********");
         }
-        setProperty(property, value);
-        return getSmtpServerProperties();
+        return new ResponseEntity<>(_notificationsPrefs.setSmtpMailProperty(property, value), HttpStatus.OK);
+    }
+
+    @ApiOperation(value = "Removes the value for a specified Java mail property.",
+            notes = "This completely removes the specified mail property. The value returned by this function contains the previous value (if any).",
+            response = String.class)
+    @ApiResponses({@ApiResponse(code = 200, message = "Property found and returned."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 403, message = "Not authorized to set the mail service properties."),
+                   @ApiResponse(code = 404, message = "Specified key not found in the mail service properties."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
+    @RequestMapping(value = "smtp/property/{property}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.DELETE)
+    public ResponseEntity<String> removeExtendedProperty(@ApiParam(value = "The mail property to be removed.", required = true) @PathVariable final String property) {
+        final HttpStatus status = isPermitted();
+        if (status != null) {
+            return new ResponseEntity<>(status);
+        }
+        if (!_notificationsPrefs.getSmtpServer().getMailProperties().containsKey(property)) {
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+        }
+        _log.info("User {} removing value for property {}", getSessionUser().getLogin(), property);
+        return new ResponseEntity<>(_notificationsPrefs.removeSmtpMailProperty(property), HttpStatus.OK);
     }
 
     @ApiOperation(value = "Sets the email message for contacting help.",
-                  notes = "Sets the email message that people should receive when contacting help.",
-                  response = Void.class)
+            notes = "Sets the email message that people should receive when contacting help.",
+            response = Void.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Help email message successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the help email message."),
@@ -403,8 +400,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets the email message for user registration.",
-                  notes = "Sets the email message that people should receive when they register. Link for email validation is auto-populated.",
-                  response = Properties.class)
+            notes = "Sets the email message that people should receive when they register. Link for email validation is auto-populated.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "User registration email message successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the user registration email message."),
@@ -416,8 +413,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets the email message for forgot username.",
-                  notes = "Sets the email message that people should receive when they click that they forgot their username.",
-                  response = Properties.class)
+            notes = "Sets the email message that people should receive when they click that they forgot their username.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Forgot username email message successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the forgot username email message."),
@@ -429,8 +426,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets the email message for password reset.",
-                  notes = "Sets the email message that people should receive when they click to reset their password.  Link for password reset is auto-populated.",
-                  response = Properties.class)
+            notes = "Sets the email message that people should receive when they click to reset their password.  Link for password reset is auto-populated.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Password reset message successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the password reset message."),
@@ -442,8 +439,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns the email message for contacting help.",
-                  notes = "This returns the email message that people should receive when contacting help.",
-                  response = String.class)
+            notes = "This returns the email message that people should receive when contacting help.",
+            response = String.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Email message for contacting help successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get email message for contacting help."),
@@ -454,8 +451,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns the email message for user registration.",
-                  notes = "This returns the email message that people should receive when they register. Link for email validation is auto-populated.",
-                  response = String.class)
+            notes = "This returns the email message that people should receive when they register. Link for email validation is auto-populated.",
+            response = String.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Email message for user registration successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get email message for user registration."),
@@ -466,8 +463,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns the email message for forgot username.",
-                  notes = "This returns the email message that people should receive when they click that they forgot their username.",
-                  response = String.class)
+            notes = "This returns the email message that people should receive when they click that they forgot their username.",
+            response = String.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Email message for forgot username successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get email message for forgot username."),
@@ -478,8 +475,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns the email message for password reset.",
-                  notes = "This returns the email message that people should receive when they click to reset their password.  Link for password reset is auto-populated.",
-                  response = String.class)
+            notes = "This returns the email message that people should receive when they click to reset their password.  Link for password reset is auto-populated.",
+            response = String.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Email message for password reset successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get email message for password reset."),
@@ -490,8 +487,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets whether admins should be notified of user registration.",
-                  notes = "Sets whether admins should be notified of user registration.",
-                  response = Void.class)
+            notes = "Sets whether admins should be notified of user registration.",
+            response = Void.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Whether admins should be notified of user registration successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set whether admins should be notified of user registration."),
@@ -503,8 +500,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets whether admins should be notified of pipeline processing submit.",
-                  notes = "Sets whether admins should be notified of pipeline processing submit.",
-                  response = Properties.class)
+            notes = "Sets whether admins should be notified of pipeline processing submit.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Whether admins should be notified of pipeline processing submit successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set whether admins should be notified of pipeline processing submit."),
@@ -516,8 +513,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets whether admins should be notified of project access requests.",
-                  notes = "Sets whether admins should be notified of project access requests.",
-                  response = Properties.class)
+            notes = "Sets whether admins should be notified of project access requests.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Whether admins should be notified of project access requests successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set whether admins should be notified of project access requests."),
@@ -529,8 +526,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets whether admins should be notified of session transfer.",
-                  notes = "Sets whether admins should be notified of session transfer by user.",
-                  response = Properties.class)
+            notes = "Sets whether admins should be notified of session transfer by user.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Whether admins should be notified of session transfer successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set whether admins should be notified of session transfer."),
@@ -542,8 +539,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns whether admins should be notified of user registration.",
-                  notes = "This returns whether admins should be notified of user registration.",
-                  response = Boolean.class)
+            notes = "This returns whether admins should be notified of user registration.",
+            response = Boolean.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Email message for contacting help successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get email message for contacting help."),
@@ -554,8 +551,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns whether admins should be notified of pipeline processing submit.",
-                  notes = "This returns whether admins should be notified of pipeline processing submit.",
-                  response = Boolean.class)
+            notes = "This returns whether admins should be notified of pipeline processing submit.",
+            response = Boolean.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Email message for user registration successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get email message for user registration."),
@@ -566,8 +563,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns whether admins should be notified of project access requests.",
-                  notes = "This returns whether admins should be notified of project access requests.",
-                  response = Boolean.class)
+            notes = "This returns whether admins should be notified of project access requests.",
+            response = Boolean.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Email message for forgot username successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get email message for forgot username."),
@@ -578,8 +575,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns whether admins should be notified of session transfer.",
-                  notes = "This returns whether admins should be notified of session transfer.",
-                  response = Boolean.class)
+            notes = "This returns whether admins should be notified of session transfer.",
+            response = Boolean.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Email message for password reset successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get email message for password reset."),
@@ -590,8 +587,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets whether non-users should be able to subscribe to notifications.",
-                  notes = "Sets whether non-users should be able to subscribe to notifications.",
-                  response = Properties.class)
+            notes = "Sets whether non-users should be able to subscribe to notifications.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Whether non-users should be able to subscribe to notifications."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set whether non-users should be able to subscribe to notifications."),
@@ -603,8 +600,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns whether non-users should be able to subscribe to notifications.",
-                  notes = "This returns whether non-users should be able to subscribe to notifications.",
-                  response = Boolean.class)
+            notes = "This returns whether non-users should be able to subscribe to notifications.",
+            response = Boolean.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Whether non-users should be able to subscribe to notifications successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get whether non-users should be able to subscribe to notifications."),
@@ -615,8 +612,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets the email addresses for error notifications.",
-                  notes = "Sets the email addresses that should be subscribed to error notifications.",
-                  response = Void.class)
+            notes = "Sets the email addresses that should be subscribed to error notifications.",
+            response = Void.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Error subscribers successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the error subscribers."),
@@ -628,8 +625,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets the email addresses for issue notifications.",
-                  notes = "Sets the email addresses that should be subscribed to issue notifications.",
-                  response = Properties.class)
+            notes = "Sets the email addresses that should be subscribed to issue notifications.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Issue subscribers successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the issue subscribers."),
@@ -641,8 +638,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets the email addresses for new user notifications.",
-                  notes = "Sets the email addresses that should be subscribed to new user notifications.",
-                  response = Properties.class)
+            notes = "Sets the email addresses that should be subscribed to new user notifications.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "New user subscribers successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the new user subscribers."),
@@ -654,8 +651,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets the email addresses for update notifications.",
-                  notes = "Sets the email addresses that should be subscribed to update notifications.",
-                  response = Properties.class)
+            notes = "Sets the email addresses that should be subscribed to update notifications.",
+            response = Properties.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Update subscribers successfully set."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to set the update subscribers."),
@@ -667,8 +664,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns list of email addresses subscribed to error notifications.",
-                  notes = "This returns a list of all the email addresses that are subscribed to receive error notifications.",
-                  response = String.class)
+            notes = "This returns a list of all the email addresses that are subscribed to receive error notifications.",
+            response = String.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Error notification subscribers successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get subscribers for email notifications."),
@@ -679,8 +676,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns list of email addresses subscribed to issue notifications.",
-                  notes = "This returns a list of all the email addresses that are subscribed to receive issue notifications.",
-                  response = String.class)
+            notes = "This returns a list of all the email addresses that are subscribed to receive issue notifications.",
+            response = String.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Issue notification subscribers successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get subscribers for email notifications."),
@@ -691,8 +688,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns list of email addresses subscribed to new user notifications.",
-                  notes = "This returns a list of all the email addresses that are subscribed to receive new user notifications.",
-                  response = String.class)
+            notes = "This returns a list of all the email addresses that are subscribed to receive new user notifications.",
+            response = String.class)
     @ApiResponses({@ApiResponse(code = 200, message = "New user notification subscribers successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get subscribers for email notifications."),
@@ -703,8 +700,8 @@ public class NotificationsApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns list of email addresses subscribed to update notifications.",
-                  notes = "This returns a list of all the email addresses that are subscribed to receive update notifications.",
-                  response = String.class)
+            notes = "This returns a list of all the email addresses that are subscribed to receive update notifications.",
+            response = String.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Update notification subscribers successfully returned."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "Not authorized to get subscribers for email notifications."),
@@ -714,51 +711,27 @@ public class NotificationsApi extends AbstractXapiRestController {
         return new ResponseEntity<>(_notificationsPrefs.getEmailRecipientUpdate(), HttpStatus.OK);
     }
 
-    protected Properties getSubmittedProperties(final Properties properties) {
-        // Set all of the submitted properties.
-        final Properties javaMailProperties = new Properties();
-        if (properties != null) {
-            for (final String property : properties.stringPropertyNames()) {
-                final String value = properties.getProperty(property);
-                if (StringUtils.isNotBlank(value)) {
-                    javaMailProperties.setProperty(property, value);
-                }
-            }
-        }
-
-        // Find any existing properties that weren't submitted...
-        final Properties existing = _javaMailSender.getJavaMailProperties();
-        for (final String property : existing.stringPropertyNames()) {
-            if (!javaMailProperties.containsKey(property)) {
-                // Set the value to "", this will remove the property.
-                javaMailProperties.setProperty(property, "");
-            }
-        }
-        return javaMailProperties;
-    }
-
     private Properties convertToProperties(final Map<String, Object> preferenceMap) throws IOException {
         final Properties properties = new Properties();
         for (final String key : preferenceMap.keySet()) {
-            final Object object = preferenceMap.get(key);
-            String tempVal = "";
-            if(object!=null){
-                if(String.class.isAssignableFrom(object.getClass())){
-                    tempVal = (String)object;
-                }
-                else{
+            final Object object  = preferenceMap.get(key);
+            String       tempVal = "";
+            if (object != null) {
+                if (String.class.isAssignableFrom(object.getClass())) {
+                    tempVal = (String) object;
+                } else {
                     tempVal = _serializer.toJson(object);
                 }
             }
-            final String value  = tempVal;
+            final String value = tempVal;
             properties.setProperty(key, value);
         }
         return properties;
     }
 
     private void cleanProperties(final Properties properties) {
-        if (properties.containsKey("host")) {
-            properties.remove("host");
+        if (properties.containsKey("hostname")) {
+            properties.remove("hostname");
         }
         if (properties.containsKey("port")) {
             properties.remove("port");
@@ -772,47 +745,20 @@ public class NotificationsApi extends AbstractXapiRestController {
         if (properties.containsKey("password")) {
             properties.remove("password");
         }
-    }
-
-    private void setHost(final String host, final boolean freakOutIfBlank) {
-        if (freakOutIfBlank && StringUtils.isBlank(host)) {
-            throw new NrgServiceRuntimeException(NrgServiceError.ConfigurationError, "You can not set the SMTP server address to an empty value!");
-        }
-        if (StringUtils.isNotBlank(host)) {
-            _javaMailSender.setHost(host);
-        }
-    }
-
-    private void setPort(final int port) {
-        if (port != -1) {
-            _javaMailSender.setPort(port);
+        if (properties.containsKey("smtpHostname")) {
+            properties.remove("smtpHostname");
         }
-    }
-
-    private void setProtocol(final String protocol) {
-        if (!StringUtils.equals(NOT_SET, protocol)) {
-            _javaMailSender.setProtocol(protocol);
+        if (properties.containsKey("smtpPort")) {
+            properties.remove("smtpPort");
         }
-    }
-
-    private void setUsername(final String username) {
-        if (!StringUtils.equals(NOT_SET, username)) {
-            _javaMailSender.setUsername(username);
+        if (properties.containsKey("smtpProtocol")) {
+            properties.remove("smtpProtocol");
         }
-    }
-
-    private void setPassword(final String password) {
-        if (!StringUtils.equals(NOT_SET, password)) {
-            _javaMailSender.setPassword(password);
+        if (properties.containsKey("smtpUsername")) {
+            properties.remove("smtpUsername");
         }
-    }
-
-    private void setProperty(final String property, final String value) {
-        final Properties properties = _javaMailSender.getJavaMailProperties();
-        if (properties.containsKey(property) && StringUtils.isBlank(value)) {
-            properties.remove(property);
-        } else {
-            properties.setProperty(property, value);
+        if (properties.containsKey("smtpPassword")) {
+            properties.remove("smtpPassword");
         }
     }
 
@@ -834,11 +780,10 @@ public class NotificationsApi extends AbstractXapiRestController {
         }
     }
 
-    private static final Logger                                 _log                           = LoggerFactory.getLogger(NotificationsApi.class);
-    private static final String                                 NOT_SET                        = "NotSet";
+    private static final Logger _log    = LoggerFactory.getLogger(NotificationsApi.class);
+    private static final String NOT_SET = "NotSet";
 
     private final NotificationsPreferences _notificationsPrefs;
-    private final JavaMailSenderImpl       _javaMailSender;
     private final XnatAppInfo              _appInfo;
     private final SerializerService        _serializer;
 }
diff --git a/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java b/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java
index b45ddd15..708cc462 100644
--- a/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java
+++ b/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java
@@ -13,14 +13,17 @@ import com.google.common.base.Joiner;
 import io.swagger.annotations.*;
 import org.apache.commons.lang3.StringUtils;
 import org.nrg.framework.annotations.XapiRestController;
+import org.nrg.framework.exceptions.NrgServiceRuntimeException;
 import org.nrg.prefs.exceptions.InvalidPreferenceName;
+import org.nrg.xapi.exceptions.ApiException;
 import org.nrg.xapi.exceptions.InitializationException;
+import org.nrg.xapi.exceptions.InsufficientPrivilegesException;
+import org.nrg.xapi.exceptions.NotFoundException;
 import org.nrg.xdat.preferences.SiteConfigPreferences;
 import org.nrg.xdat.rest.AbstractXapiRestController;
 import org.nrg.xdat.security.services.RoleHolder;
 import org.nrg.xdat.security.services.UserManagementServiceI;
 import org.nrg.xnat.services.XnatAppInfo;
-import org.nrg.xnat.turbine.utils.ArcSpecManager;
 import org.nrg.xnat.utils.XnatHttpUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -102,7 +105,7 @@ public class SiteConfigApi extends AbstractXapiRestController {
                    @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."),
                    @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE, MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.POST)
-    public ResponseEntity<Void> setSiteConfigProperties(@ApiParam(value = "The map of site configuration properties to be set.", required = true) @RequestBody final Map<String, String> properties) throws InitializationException {
+    public ResponseEntity<Void> setSiteConfigProperties(@ApiParam(value = "The map of site configuration properties to be set.", required = true) @RequestBody final Map<String, String> properties) throws ApiException, InitializationException {
         final HttpStatus status = isPermitted();
         if (status != null) {
             return new ResponseEntity<>(status);
@@ -116,6 +119,12 @@ public class SiteConfigApi extends AbstractXapiRestController {
                 if (isInitializing && name.equals("initialized")) {
                     continue;
                 }
+                if (name.equals("receivedFileUser")) {
+                    final HttpStatus setStatus = setReceivedFileUser(properties.get(name));
+                    if (setStatus != null) {
+                        return new ResponseEntity<>(setStatus);
+                    }
+                }
                 _preferences.set(properties.get(name), name);
                 if (_log.isInfoEnabled()) {
                     _log.info("Set property {} to value: {}", name, properties.get(name));
@@ -127,10 +136,7 @@ public class SiteConfigApi extends AbstractXapiRestController {
 
         // If we're initializing...
         if (isInitializing) {
-            // Make the final initialization call.
-            initialize();
-
-            // Now make the initialized setting true.
+            // Now make the initialized setting true. This will kick off the initialized event handler.
             _preferences.setInitialized(true);
         }
 
@@ -191,7 +197,8 @@ public class SiteConfigApi extends AbstractXapiRestController {
                    @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."),
                    @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = "{property}", consumes = {MediaType.TEXT_PLAIN_VALUE, MediaType.APPLICATION_JSON_VALUE}, produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST)
-    public ResponseEntity<Void> setSiteConfigProperty(@ApiParam(value = "The property to be set.", required = true) @PathVariable("property") final String property, @ApiParam("The value to be set for the property.") @RequestBody final String value) throws InitializationException {
+    public ResponseEntity<Void> setSiteConfigProperty(@ApiParam(value = "The property to be set.", required = true) @PathVariable("property") final String property,
+                                                      @ApiParam("The value to be set for the property.") @RequestBody final String value) throws InitializationException, ApiException {
         final HttpStatus status = isPermitted();
         if (status != null) {
             return new ResponseEntity<>(status);
@@ -202,8 +209,12 @@ public class SiteConfigApi extends AbstractXapiRestController {
         }
 
         if (StringUtils.equals("initialized", property) && StringUtils.equals("true", value)) {
-            initialize();
             _preferences.setInitialized(true);
+        } else if (StringUtils.equals("receivedFileUser", property)) {
+            final HttpStatus setStatus = setReceivedFileUser(value);
+            if (setStatus != null) {
+                return new ResponseEntity<>(setStatus);
+            }
         } else {
             try {
                 _preferences.set(value, property);
@@ -268,6 +279,24 @@ public class SiteConfigApi extends AbstractXapiRestController {
         return new ResponseEntity<>(_appInfo.getFormattedUptime(), HttpStatus.OK);
     }
 
+    private HttpStatus setReceivedFileUser(final String value) throws InsufficientPrivilegesException, NotFoundException {
+        try {
+            _preferences.setReceivedFileUser(value);
+        } catch (NrgServiceRuntimeException e) {
+            switch (e.getServiceError()) {
+                case PermissionsViolation:
+                    throw new InsufficientPrivilegesException(e.getMessage());
+                case UserNotFoundError:
+                    throw new NotFoundException("No user with the name " + e.getMessage() + " was found.");
+                case Unknown:
+                default:
+                    _log.error("An unknown error occurred trying to set the received file user to value " + value, e);
+                    return HttpStatus.INTERNAL_SERVER_ERROR;
+            }
+        }
+        return null;
+    }
+
     private Map<String, Object> getPreferences() {
         if (!_hasFoundPreferences) {
             return _preferences.getPreferenceMap();
@@ -277,17 +306,6 @@ public class SiteConfigApi extends AbstractXapiRestController {
         return preferences;
     }
 
-    private void initialize() throws InitializationException {
-        // In the case where the application hasn't yet been initialized, this operation should mean that the system is
-        // being initialized from the set-up page. In that case, we need to propagate a few properties to the arc-spec
-        // persistence to support
-        try {
-            ArcSpecManager.initialize(getSessionUser());
-        } catch (Exception e) {
-            throw new InitializationException(e);
-        }
-    }
-
     private static final Logger _log = LoggerFactory.getLogger(SiteConfigApi.class);
 
     private final SiteConfigPreferences _preferences;
diff --git a/src/main/java/org/nrg/xapi/rest/users/UsersApi.java b/src/main/java/org/nrg/xapi/rest/users/UsersApi.java
index 248ccc1c..0f3412df 100644
--- a/src/main/java/org/nrg/xapi/rest/users/UsersApi.java
+++ b/src/main/java/org/nrg/xapi/rest/users/UsersApi.java
@@ -134,20 +134,30 @@ public class UsersApi extends AbstractXapiRestController {
             } else {
                 username = principal.toString();
             }
-            final Map<String, Object> sessionData = new HashMap<>();
             final List<SessionInformation> sessions = _sessionRegistry.getAllSessions(principal, false);
+
+            // Sometimes there are no sessions, which is weird but OK, we don't want to see those entries.
+            final int count = sessions.size();
+            if (count == 0) {
+                continue;
+            }
+
+            // Now add user with a session or more to the list of active users.
             final ArrayList<String> sessionIds = new ArrayList<>();
             for (final SessionInformation session : sessions) {
                 sessionIds.add(session.getSessionId());
             }
+
+            final Map<String, Object> sessionData = new HashMap<>();
             sessionData.put("sessions", sessionIds);
-            sessionData.put("count", sessions.size());
+            sessionData.put("count", count);
+
             activeUsers.put(username, sessionData);
         }
         return new ResponseEntity<>(activeUsers, HttpStatus.OK);
     }
 
-    @ApiOperation(value = "Get information about active sessions for the indicated user.", notes = "Returns a map containing a list of session IDs usernames for users that have at least one currently active session, i.e. logged in or associated with a valid application session. This also includes the number of active sessions for each user.", response = String.class, responseContainer = "List")
+    @ApiOperation(value = "Get information about active sessions for the indicated user.", notes = "Returns a map containing a list of session IDs and usernames for users that have at least one currently active session, i.e. logged in or associated with a valid application session. This also includes the number of active sessions for each user.", response = String.class, responseContainer = "List")
     @ApiResponses({@ApiResponse(code = 200, message = "A list of active users."),
                    @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
                    @ApiResponse(code = 403, message = "You do not have sufficient permissions to access the list of usernames."),
diff --git a/src/main/java/org/nrg/xnat/archive/Transfer.java b/src/main/java/org/nrg/xnat/archive/Transfer.java
index 367114e0..a8f6c11c 100644
--- a/src/main/java/org/nrg/xnat/archive/Transfer.java
+++ b/src/main/java/org/nrg/xnat/archive/Transfer.java
@@ -130,7 +130,7 @@ public class Transfer {
             xnatPipelineLauncher.setParameter("userfullname", XnatPipelineLauncher.getUserName(user));
             xnatPipelineLauncher.setParameter("adminemail", admin_email);
             xnatPipelineLauncher.setParameter("xnatserver", system);
-            xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
+            xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().getHostname());
             xnatPipelineLauncher.setParameter("sessionType", mr.getXSIType());
             xnatPipelineLauncher.setParameter("xnat_project", mr.getProject());
             xnatPipelineLauncher.setParameter("logDir", XDAT.getSiteConfigPreferences().getCachePath() + "logs" + "/" + "transfer");
diff --git a/src/main/java/org/nrg/xnat/configuration/NotificationsConfig.java b/src/main/java/org/nrg/xnat/configuration/NotificationsConfig.java
index 188e2c98..9b98c513 100644
--- a/src/main/java/org/nrg/xnat/configuration/NotificationsConfig.java
+++ b/src/main/java/org/nrg/xnat/configuration/NotificationsConfig.java
@@ -18,6 +18,7 @@ import org.nrg.notify.renderers.ChannelRenderer;
 import org.nrg.notify.renderers.NrgMailChannelRenderer;
 import org.nrg.xdat.preferences.NotificationsPreferences;
 import org.nrg.xdat.preferences.SiteConfigPreferences;
+import org.nrg.xdat.preferences.SmtpServer;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
@@ -27,7 +28,6 @@ import java.io.IOException;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Properties;
 
 @Configuration
 @ComponentScan({"org.nrg.mail.services", "org.nrg.notify.services.impl", "org.nrg.notify.daos"})
@@ -35,20 +35,16 @@ public class NotificationsConfig {
 
     @Bean
     public JavaMailSenderImpl mailSender(final NotificationsPreferences preferences) throws IOException, SiteConfigurationException {
-        final Map<String, String> smtp = preferences.getSmtpServer();
+        final SmtpServer         smtp   = preferences.getSmtpServer();
         final JavaMailSenderImpl sender = new JavaMailSenderImpl();
         if(smtp!=null) {
-            sender.setHost(StringUtils.defaultIfBlank(smtp.remove("host"), "localhost"));
-            sender.setPort(Integer.parseInt(StringUtils.defaultIfBlank(smtp.remove("port"), "25")));
-            sender.setUsername(StringUtils.defaultIfBlank(smtp.remove("username"), ""));
-            sender.setPassword(StringUtils.defaultIfBlank(smtp.remove("password"), ""));
-            sender.setProtocol(StringUtils.defaultIfBlank(smtp.remove("protocol"), "smtp"));
-            if (smtp.size() > 0) {
-                final Properties properties = new Properties();
-                for (final String property : smtp.keySet()) {
-                    properties.setProperty(property, smtp.get(property));
-                }
-                sender.setJavaMailProperties(properties);
+            sender.setHost(StringUtils.defaultIfBlank(smtp.getHostname(), "localhost"));
+            sender.setPort(smtp.getPort());
+            sender.setUsername(StringUtils.defaultIfBlank(smtp.getUsername(), ""));
+            sender.setPassword(StringUtils.defaultIfBlank(smtp.getPassword(), ""));
+            sender.setProtocol(StringUtils.defaultIfBlank(smtp.getProtocol(), "smtp"));
+            if (smtp.getMailProperties().size() > 0) {
+                sender.setJavaMailProperties(smtp.getMailProperties());
             }
         }
         return sender;
diff --git a/src/main/java/org/nrg/xnat/configuration/PreferencesConfig.java b/src/main/java/org/nrg/xnat/configuration/PreferencesConfig.java
index 2c6e1578..8262729f 100644
--- a/src/main/java/org/nrg/xnat/configuration/PreferencesConfig.java
+++ b/src/main/java/org/nrg/xnat/configuration/PreferencesConfig.java
@@ -9,26 +9,19 @@
 
 package org.nrg.xnat.configuration;
 
-import org.nrg.config.exceptions.SiteConfigurationException;
 import org.nrg.config.services.ConfigService;
-import org.nrg.config.services.SiteConfigurationService;
 import org.nrg.config.services.UserConfigurationService;
 import org.nrg.config.services.impl.DefaultConfigService;
 import org.nrg.config.services.impl.DefaultUserConfigurationService;
 import org.nrg.prefs.configuration.NrgPrefsConfiguration;
-import org.nrg.prefs.services.NrgPreferenceService;
 import org.nrg.prefs.services.PreferenceService;
-import org.nrg.xdat.preferences.SiteConfigPreferences;
 import org.nrg.xnat.resolvers.XnatPreferenceEntityResolver;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
-import org.springframework.core.env.Environment;
 
 import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 
 @Configuration
 @ComponentScan("org.nrg.config.daos")
@@ -45,26 +38,6 @@ public class PreferencesConfig {
         return new DefaultUserConfigurationService(configService());
     }
 
-    @Bean
-    public SiteConfigurationService siteConfigurationService(final SiteConfigPreferences preferences, final NrgPreferenceService nrgPreferenceService, final ConfigService configService, final Environment environment) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException {
-        final Class<? extends SiteConfigurationService> clazz = Class.forName(preferences.getSiteConfigurationService()).asSubclass(SiteConfigurationService.class);
-        try {
-            @SuppressWarnings("unchecked")
-            final Constructor<? extends SiteConfigurationService> constructor = clazz.getConstructor(NrgPreferenceService.class, Environment.class);
-            return constructor.newInstance(nrgPreferenceService, environment);
-        } catch (NoSuchMethodException | InvocationTargetException ignored) {
-            // No worries, it just doesn't have that constructor.
-        }
-        try {
-            @SuppressWarnings("unchecked")
-            final Constructor<? extends SiteConfigurationService> constructor = clazz.getConstructor(ConfigService.class, Environment.class);
-            return constructor.newInstance(configService, environment);
-        } catch (NoSuchMethodException | InvocationTargetException ignored) {
-            // No worries, it just doesn't have that constructor.
-        }
-        return clazz.newInstance();
-    }
-
     @Bean
     public XnatPreferenceEntityResolver defaultResolver(final PreferenceService preferenceService) throws IOException {
         return new XnatPreferenceEntityResolver(preferenceService);
diff --git a/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java b/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java
index d867e03f..21a34ed9 100644
--- a/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java
+++ b/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java
@@ -71,12 +71,12 @@ public class SchedulerConfig implements SchedulingConfigurer {
         _service.triggerEvent(new PreferenceEvent("inactivityBeforeLockout", String.valueOf(_siteConfigPreferences.getInactivityBeforeLockout())));
         _service.triggerEvent(new PreferenceEvent("maxFailedLoginsLockoutDuration", String.valueOf(_siteConfigPreferences.getMaxFailedLoginsLockoutDuration())));
         _service.triggerEvent(new PreferenceEvent("emailPrefix", String.valueOf(_notificationsPreferences.getEmailPrefix())));
-        _service.triggerEvent(new PreferenceEvent("host", String.valueOf(_notificationsPreferences.getHostname())));
+        _service.triggerEvent(new PreferenceEvent("smtpHostname", String.valueOf(_notificationsPreferences.getSmtpHostname())));
         _service.triggerEvent(new PreferenceEvent("requireLogin", String.valueOf(_siteConfigPreferences.getRequireLogin())));
-        _service.triggerEvent(new PreferenceEvent("security.channel", String.valueOf(_siteConfigPreferences.getSecurityChannel())));
+        _service.triggerEvent(new PreferenceEvent("securityChannel", String.valueOf(_siteConfigPreferences.getSecurityChannel())));
         _service.triggerEvent(new PreferenceEvent("passwordExpirationType", String.valueOf(_siteConfigPreferences.getPasswordExpirationType())));
         _service.triggerEvent(new PreferenceEvent("archivePath", String.valueOf(_siteConfigPreferences.getArchivePath())));
-        _service.triggerEvent(new PreferenceEvent("security.services.role.default", String.valueOf(_siteConfigPreferences.getRoleService())));
+        _service.triggerEvent(new PreferenceEvent("roleService", String.valueOf(_siteConfigPreferences.getRoleService())));
         _service.triggerEvent(new PreferenceEvent("checksums", String.valueOf(_siteConfigPreferences.getChecksums())));
         _service.triggerEvent(new PreferenceEvent("sitewidePetTracers", String.valueOf(_siteConfigPreferences.getSitewidePetTracers())));
 
diff --git a/src/main/java/org/nrg/xnat/event/listeners/SiteConfigPreferenceHandler.java b/src/main/java/org/nrg/xnat/event/listeners/SiteConfigPreferenceHandler.java
index 6e29b30a..3af8c555 100644
--- a/src/main/java/org/nrg/xnat/event/listeners/SiteConfigPreferenceHandler.java
+++ b/src/main/java/org/nrg/xnat/event/listeners/SiteConfigPreferenceHandler.java
@@ -9,8 +9,6 @@
 
 package org.nrg.xnat.event.listeners;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.nrg.prefs.events.AbstractPreferenceHandler;
 import org.nrg.prefs.events.PreferenceHandlerMethod;
 import org.nrg.xdat.preferences.PreferenceEvent;
@@ -24,35 +22,31 @@ import java.util.List;
 
 @Service
 public class SiteConfigPreferenceHandler extends AbstractPreferenceHandler<PreferenceEvent> {
-	private String _toolId=SiteConfigPreferences.SITE_CONFIG_TOOL_ID;
-	private final List<PreferenceHandlerMethod> _methods = new ArrayList<>();
-
-	@Inject
-	public SiteConfigPreferenceHandler(final EventBus eventBus){
-		super(eventBus);
-	}
-
-	@Override
-	public String getToolId() {
-		return _toolId;
-	}
-
-	@Override
-	public void setToolId(String toolId) {
-		_toolId=toolId;
-	}
-
-	@Override
-	public List<PreferenceHandlerMethod> getMethods(){
-		return _methods;
-	}
-
-	@Override
-	public void addMethod(PreferenceHandlerMethod method){
-		_methods.add(method);
-	}
-
-	private static final Log _log = LogFactory.getLog(SiteConfigPreferenceHandler.class);
-
-
+    private       String                        _toolId  = SiteConfigPreferences.SITE_CONFIG_TOOL_ID;
+    private final List<PreferenceHandlerMethod> _methods = new ArrayList<>();
+
+    @Inject
+    public SiteConfigPreferenceHandler(final EventBus eventBus) {
+        super(eventBus);
+    }
+
+    @Override
+    public String getToolId() {
+        return _toolId;
+    }
+
+    @Override
+    public void setToolId(String toolId) {
+        _toolId = toolId;
+    }
+
+    @Override
+    public List<PreferenceHandlerMethod> getMethods() {
+        return _methods;
+    }
+
+    @Override
+    public void addMethod(PreferenceHandlerMethod method) {
+        _methods.add(method);
+    }
 }
diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/FeatureServicesHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/FeatureServicesHandlerMethod.java
index a3f8a091..4e682c48 100644
--- a/src/main/java/org/nrg/xnat/event/listeners/methods/FeatureServicesHandlerMethod.java
+++ b/src/main/java/org/nrg/xnat/event/listeners/methods/FeatureServicesHandlerMethod.java
@@ -11,8 +11,6 @@ package org.nrg.xnat.event.listeners.methods;
 
 import com.google.common.collect.ImmutableList;
 import org.nrg.xdat.security.helpers.Features;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
 import java.util.Arrays;
@@ -46,7 +44,6 @@ public class FeatureServicesHandlerMethod extends AbstractSiteConfigPreferenceHa
         Features.setFeatureRepositoryServiceToSiteConfigPreference();
     }
 
-    private static final Logger       _log        = LoggerFactory.getLogger(FeatureServicesHandlerMethod.class);
-    private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("security.services.feature.default", "security.services.featureRepository.default"));
+    private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("featureService", "featureRepositoryService"));
 
 }
diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/InitializedHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/InitializedHandlerMethod.java
new file mode 100644
index 00000000..ea96b98c
--- /dev/null
+++ b/src/main/java/org/nrg/xnat/event/listeners/methods/InitializedHandlerMethod.java
@@ -0,0 +1,106 @@
+/*
+ * web: org.nrg.xnat.event.listeners.methods.RequiredChannelHandlerMethod
+ * XNAT http://www.xnat.org
+ * Copyright (c) 2016, Washington University School of Medicine and Howard Hughes Medical Institute
+ * All Rights Reserved
+ *
+ * Released under the Simplified BSD.
+ */
+
+package org.nrg.xnat.event.listeners.methods;
+
+import com.google.common.collect.ImmutableList;
+import org.nrg.framework.exceptions.NrgServiceError;
+import org.nrg.framework.exceptions.NrgServiceRuntimeException;
+import org.nrg.xapi.exceptions.InitializationException;
+import org.nrg.xdat.preferences.SiteConfigPreferences;
+import org.nrg.xnat.turbine.utils.ArcSpecManager;
+import org.nrg.xnat.utils.XnatUserProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class InitializedHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod {
+    @Autowired
+    public InitializedHandlerMethod(final SiteConfigPreferences preferences, final XnatUserProvider primaryAdminUserProvider) {
+        super(primaryAdminUserProvider);
+        _preferences = preferences;
+    }
+
+    @Override
+    public List<String> getHandledPreferences() {
+        return PREFERENCES;
+    }
+
+    @Override
+    public void handlePreferences(final Map<String, String> values) {
+        if (values.containsKey(INITIALIZED)) {
+            handlePreference(INITIALIZED, values.get(INITIALIZED));
+        }
+    }
+
+    @Override
+    public void handlePreference(final String preference, final String value) {
+        if (PREFERENCES.contains(preference)) {
+            try {
+                initialize();
+            } catch (InitializationException e) {
+                throw new NrgServiceRuntimeException(NrgServiceError.Unknown, "An error occurred attempting to complete system initialization", e);
+            }
+        }
+    }
+
+    private void initialize() throws InitializationException {
+        final String adminEmail = _preferences.getAdminEmail();
+        final String archivePath = _preferences.getArchivePath();
+        final String buildPath = _preferences.getBuildPath();
+        final String cachePath = _preferences.getCachePath();
+        final boolean enableCsrfToken = _preferences.getEnableCsrfToken();
+        final String ftpPath = _preferences.getFtpPath();
+        final String pipelinePath = _preferences.getPipelinePath();
+        final String prearchivePath = _preferences.getPrearchivePath();
+        final boolean requireLogin = _preferences.getRequireLogin();
+        final String siteId = _preferences.getSiteId();
+        final String siteUrl = _preferences.getSiteUrl();
+        final boolean userRegistration = _preferences.getUserRegistration();
+
+        // TODO: We may actually need to put a null check in here and make this a Future that circles back once everything is properly initialized.
+        final StringBuilder buffer = new StringBuilder("Preparing to complete system initialization with the final property settings of:").append(System.lineSeparator());
+        buffer.append(" * adminEmail: ").append(adminEmail).append(System.lineSeparator());
+        buffer.append(" * archivePath: ").append(archivePath).append(System.lineSeparator());
+        buffer.append(" * buildPath: ").append(buildPath).append(System.lineSeparator());
+        buffer.append(" * cachePath: ").append(cachePath).append(System.lineSeparator());
+        buffer.append(" * enableCsrfToken: ").append(enableCsrfToken).append(System.lineSeparator());
+        buffer.append(" * ftpPath: ").append(ftpPath).append(System.lineSeparator());
+        buffer.append(" * pipelinePath: ").append(pipelinePath).append(System.lineSeparator());
+        buffer.append(" * prearchivePath: ").append(prearchivePath).append(System.lineSeparator());
+        buffer.append(" * requireLogin: ").append(requireLogin).append(System.lineSeparator());
+        buffer.append(" * siteId: ").append(siteId).append(System.lineSeparator());
+        buffer.append(" * siteUrl: ").append(siteUrl).append(System.lineSeparator());
+        buffer.append(" * userRegistration: ").append(userRegistration).append(System.lineSeparator());
+
+        _log.info(buffer.toString());
+
+        // In the case where the application hasn't yet been initialized, this operation should mean that the system is
+        // being initialized from the set-up page. In that case, we need to propagate a few properties to the arc-spec
+        // persistence to support
+        try {
+            ArcSpecManager.initialize(getAdminUser());
+        } catch (Exception e) {
+            throw new InitializationException(e);
+        }
+    }
+
+    private static final Logger _log = LoggerFactory.getLogger(InitializedHandlerMethod.class);
+
+    private static final String       INITIALIZED = "initialized";
+    private static final List<String> PREFERENCES = ImmutableList.copyOf(Collections.singletonList(INITIALIZED));
+
+    private final SiteConfigPreferences _preferences;
+}
diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/RequiredChannelHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/RequiredChannelHandlerMethod.java
index 87950b79..287d41d7 100644
--- a/src/main/java/org/nrg/xnat/event/listeners/methods/RequiredChannelHandlerMethod.java
+++ b/src/main/java/org/nrg/xnat/event/listeners/methods/RequiredChannelHandlerMethod.java
@@ -50,7 +50,7 @@ public class RequiredChannelHandlerMethod extends AbstractSiteConfigPreferenceHa
         _filter.setRequiredChannel(_preferences.getSecurityChannel());
     }
 
-    private static final List<String> PREFERENCES = ImmutableList.copyOf(Collections.singletonList("security.channel"));
+    private static final List<String> PREFERENCES = ImmutableList.copyOf(Collections.singletonList("securityChannel"));
 
     private final SiteConfigPreferences              _preferences;
     private final TranslatingChannelProcessingFilter _filter;
diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/RoleServicesHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/RoleServicesHandlerMethod.java
index 2299b72f..0c503241 100644
--- a/src/main/java/org/nrg/xnat/event/listeners/methods/RoleServicesHandlerMethod.java
+++ b/src/main/java/org/nrg/xnat/event/listeners/methods/RoleServicesHandlerMethod.java
@@ -77,7 +77,7 @@ public class RoleServicesHandlerMethod extends AbstractSiteConfigPreferenceHandl
     }
 
     private static final Logger       _log        = LoggerFactory.getLogger(RoleServicesHandlerMethod.class);
-    private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("security.services.role.default", "security.services.roleRepository.default"));
+    private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("roleService", "roleRepositoryService"));
 
     private final SiteConfigPreferences _preferences;
     private final RoleHolder            _roleHolder;
diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/SmtpHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/SmtpHandlerMethod.java
index 296967f0..e21fd61e 100644
--- a/src/main/java/org/nrg/xnat/event/listeners/methods/SmtpHandlerMethod.java
+++ b/src/main/java/org/nrg/xnat/event/listeners/methods/SmtpHandlerMethod.java
@@ -10,8 +10,9 @@
 package org.nrg.xnat.event.listeners.methods;
 
 import com.google.common.collect.ImmutableList;
-import org.nrg.mail.services.MailService;
+import org.apache.commons.lang.StringUtils;
 import org.nrg.xdat.preferences.NotificationsPreferences;
+import org.nrg.xdat.preferences.SmtpServer;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.mail.javamail.JavaMailSenderImpl;
 import org.springframework.stereotype.Component;
@@ -21,10 +22,9 @@ import java.util.*;
 @Component
 public class SmtpHandlerMethod extends AbstractNotificationsPreferenceHandlerMethod {
     @Autowired
-    public SmtpHandlerMethod(final NotificationsPreferences preferences, final JavaMailSenderImpl mailSender, final MailService mailService) {
+    public SmtpHandlerMethod(final NotificationsPreferences preferences, final JavaMailSenderImpl mailSender) {
         _preferences = preferences;
-        this._mailSender = mailSender;
-        _mailService = mailService;
+        _mailSender = mailSender;
     }
 
     @Override
@@ -34,48 +34,44 @@ public class SmtpHandlerMethod extends AbstractNotificationsPreferenceHandlerMet
 
     @Override
     public void handlePreferences(final Map<String, String> values) {
-        if (!Collections.disjoint(PREFERENCES, values.keySet())) {
-            updateSmtp();
-        }
+        updateSmtp();
     }
 
     @Override
     public void handlePreference(final String preference, final String value) {
-        if (PREFERENCES.contains(preference)) {
-            updateSmtp();
-        }
+        updateSmtp();
     }
 
     private void updateSmtp() {
-        final Properties oldMailProperties = _mailSender.getJavaMailProperties();
-
-        final boolean smtpEnabled = _preferences.getSmtpEnabled();
-        final boolean smtpAuth = _preferences.getSmtpAuth();
-        final boolean startTls = _preferences.getSmtpStartTls();
-        final String sslTrust = _preferences.getSmtpSSLTrust();
-
-        _mailSender.setHost(_preferences.getHostname());
-        _mailSender.setPort(_preferences.getPort());
-        _mailSender.setUsername(_preferences.getUsername());
-        _mailSender.setPassword(_preferences.getPassword());
-        _mailSender.setProtocol(_preferences.getProtocol());
-        _mailService.setSmtpEnabled(smtpEnabled);
-
-        oldMailProperties.setProperty("smtp.enabled", String.valueOf(smtpEnabled));
-        oldMailProperties.setProperty("mail.smtp.auth", String.valueOf(smtpAuth));
-        oldMailProperties.setProperty("mail.smtp.starttls.enable", String.valueOf(startTls));
-
-        if (sslTrust != null) {
-            oldMailProperties.setProperty("mail.smtp.ssl.trust", sslTrust);
+        final SmtpServer smtpServer = _preferences.getSmtpServer();
+
+        _mailSender.setHost(smtpServer.getHostname());
+        _mailSender.setPort(smtpServer.getPort());
+        _mailSender.setUsername(smtpServer.getUsername());
+        _mailSender.setPassword(smtpServer.getPassword());
+        _mailSender.setProtocol(smtpServer.getProtocol());
+
+        if (!smtpServer.getSmtpAuth()) {
+            _mailSender.setJavaMailProperties(SMTP_AUTH_DISABLED);
+        } else {
+            final Properties properties = new Properties();
+            properties.setProperty(SmtpServer.SMTP_KEY_AUTH, "true");
+            if (smtpServer.getSmtpStartTls()) {
+                properties.setProperty(SmtpServer.SMTP_KEY_STARTTLS_ENABLE, "true");
+            }
+            if (StringUtils.isNotBlank(smtpServer.getSmtpSslTrust())) {
+                properties.setProperty(SmtpServer.SMTP_KEY_SSL_TRUST, smtpServer.getSmtpSslTrust());
+            }
+            properties.putAll(smtpServer.getMailProperties());
+            _mailSender.setJavaMailProperties(properties);
         }
-
-        _mailSender.setJavaMailProperties(oldMailProperties);
     }
 
-    private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("smtp.enabled", "host", "port", "username", "password", "protocol", "smtp.enabled", "mail.smtp.auth", "mail.smtp.starttls.enable", "mail.smtp.ssl.trust"));
+    private static final List<String> PREFERENCES        = ImmutableList.copyOf(Arrays.asList("smtpEnabled", "smtpHostname", "smtpPort", "smtpUsername", "smtpPassword", "smtpProtocol", "smtpAuth", "smtpStartTls", "smtpSslTrust"));
+    private static final Properties   SMTP_AUTH_DISABLED = new Properties() {{
+        setProperty(SmtpServer.SMTP_KEY_AUTH, "false");
+    }};
 
     private final NotificationsPreferences _preferences;
     private final JavaMailSenderImpl       _mailSender;
-    private final MailService              _mailService;
-
 }
diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/XnatUserProviderPreferenceHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/XnatUserProviderPreferenceHandlerMethod.java
new file mode 100644
index 00000000..91807ce7
--- /dev/null
+++ b/src/main/java/org/nrg/xnat/event/listeners/methods/XnatUserProviderPreferenceHandlerMethod.java
@@ -0,0 +1,52 @@
+/*
+ * web: org.nrg.xnat.event.listeners.methods.ReceivedFileUserPreferenceHandlerMethod
+ * XNAT http://www.xnat.org
+ * Copyright (c) 2016, Washington University School of Medicine
+ * All Rights Reserved
+ *
+ * Released under the Simplified BSD.
+ */
+
+package org.nrg.xnat.event.listeners.methods;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.lang3.StringUtils;
+import org.nrg.xnat.utils.XnatUserProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class XnatUserProviderPreferenceHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod {
+    @Autowired
+    public XnatUserProviderPreferenceHandlerMethod(final Map<String, XnatUserProvider> providers) {
+        _providers = Maps.newHashMap(providers);
+    }
+
+    @Override
+    public List<String> getHandledPreferences() {
+        return new ArrayList<>(_providers.keySet());
+    }
+
+    @Override
+    public void handlePreferences(final Map<String, String> values) {
+        for (final String key : values.keySet()) {
+            handlePreference(key, values.get(key));
+        }
+    }
+
+    @Override
+    public void handlePreference(final String preference, final String value) {
+        if (_providers.containsKey(preference)) {
+            final XnatUserProvider provider = _providers.get(preference);
+            if (!StringUtils.equals(value, provider.getLogin())) {
+                provider.setLogin(value);
+            }
+        }
+    }
+
+    private final Map<String, XnatUserProvider> _providers;
+}
diff --git a/src/main/java/org/nrg/xnat/helpers/prearchive/PrearcUtils.java b/src/main/java/org/nrg/xnat/helpers/prearchive/PrearcUtils.java
index dd82e99f..2850af58 100644
--- a/src/main/java/org/nrg/xnat/helpers/prearchive/PrearcUtils.java
+++ b/src/main/java/org/nrg/xnat/helpers/prearchive/PrearcUtils.java
@@ -15,6 +15,7 @@ import org.apache.commons.io.filefilter.DirectoryFileFilter;
 import org.apache.commons.lang3.StringUtils;
 import org.nrg.config.entities.Configuration;
 import org.nrg.framework.constants.Scope;
+import org.nrg.xapi.exceptions.InsufficientPrivilegesException;
 import org.nrg.xdat.XDAT;
 import org.nrg.xdat.model.ArcProjectI;
 import org.nrg.xdat.om.ArcProject;
@@ -223,12 +224,11 @@ public class PrearcUtils {
     public static File getPrearcDir(final UserI user, final String project, final boolean allowUnassigned) throws Exception {
         String prearcPath;
         String prearchRootPref = XDAT.getSiteConfigPreferences().getPrearchivePath();
-        String prearchRootArcSpec = ArcSpecManager.GetInstance().getGlobalPrearchivePath();
         if (project == null || project.equals(COMMON)) {
             if (allowUnassigned || user == null || Roles.isSiteAdmin(user)) {
                 prearcPath = prearchRootPref;
             } else {
-                throw new InvalidPermissionException("user " + user.getUsername() + " does not have permission to access the Unassigned directory ");
+                throw new InsufficientPrivilegesException(user.getUsername());
             }
         } else {
             //Refactored to remove unnecessary database hits.  It only needs to hit the xnat_projectdata table if the query is using a project alias rather than a project id.  TO
@@ -306,8 +306,8 @@ public class PrearcUtils {
      * @param project If the project is null, it is the unassigned project
      *                project abbreviation or alias
      * @return true if the user has permissions to access the project, false otherwise
-     * @throws Exception
-     * @throws IOException
+     * @throws Exception When something goes wrong.
+     * @throws IOException When an error occurs reading or writing data.
      */
     @SuppressWarnings("unused")
     public static boolean validUser(final UserI user, final String project, final boolean allowUnassigned) throws Exception {
@@ -525,7 +525,7 @@ public class PrearcUtils {
     }
 
     public static String makeUri(final String urlBase, final String timestamp, final String folderName) {
-        return StringUtils.join(new String[]{urlBase, "/", timestamp, "/", folderName});
+        return StringUtils.join(urlBase, "/", timestamp, "/", folderName);
     }
 
     public static Map<String, Object> parseURI(final String uri) throws MalformedURLException {
@@ -533,7 +533,7 @@ public class PrearcUtils {
     }
 
     public static String buildURI(final String project, final String timestamp, final String folderName) {
-        return StringUtils.join(new String[]{"/prearchive/projects/", (project == null) ? PrearcUtils.COMMON : project, "/", timestamp, "/", folderName});
+        return StringUtils.join("/prearchive/projects/", (project == null) ? PrearcUtils.COMMON : project, "/", timestamp, "/", folderName);
     }
 
     public static XFTTable convertArrayLtoTable(ArrayList<ArrayList<Object>> rows) {
@@ -809,8 +809,8 @@ public class PrearcUtils {
      * @param session  The session to be locked.
      * @param filename The filename to be locked.
      * @return PrearcFileLock
-     * @throws SessionFileLockException
-     * @throws IOException
+     * @throws SessionFileLockException When an attempt is made to access a locked file.
+     * @throws IOException When an error occurs reading or writing data.
      */
     public static PrearcFileLock lockFile(final SessionDataTriple session, final String filename) throws SessionFileLockException, IOException {
         //putting these in a subdirectory of the cache space
@@ -858,19 +858,26 @@ public class PrearcUtils {
 
         synchronized (syncLock) {
             //synchronized to prevent overlap with .lockFile()
-            if (name.exists() && (name.list() == null || name.list().length == 0)) {
-                try {
-                    FileUtils.deleteDirectory(name);
-
-                    if (timestamp.exists() && (timestamp.list() == null || timestamp.list().length == 0)) {
-                        FileUtils.deleteDirectory(timestamp);
-
-                        if (project.exists() && (project.list() == null || project.list().length == 0)) {
-                            FileUtils.deleteDirectory(project);
+            if (name.exists()) {
+                final String[] names = name.list();
+                if (names == null || names.length == 0) {
+                    try {
+                        FileUtils.deleteDirectory(name);
+                        if (timestamp.exists()) {
+                            final String[] timestamps = timestamp.list();
+                            if (timestamps == null || timestamps.length == 0) {
+                                FileUtils.deleteDirectory(timestamp);
+                                if (project.exists()) {
+                                    final String[] projects = project.list();
+                                    if (projects == null || projects.length == 0) {
+                                        FileUtils.deleteDirectory(project);
+                                    }
+                                }
+                            }
                         }
+                    } catch (IOException e) {
+                        logger.error("Couldn't clean temporary lock directories in the cache folder.", e);
                     }
-                } catch (IOException e) {
-                    logger.error("Couldn't clean temporary lock directories in the cache folder.", e);
                 }
             }
         }
diff --git a/src/main/java/org/nrg/xnat/restlet/actions/TriggerPipelines.java b/src/main/java/org/nrg/xnat/restlet/actions/TriggerPipelines.java
index e3570b3b..a30abd94 100644
--- a/src/main/java/org/nrg/xnat/restlet/actions/TriggerPipelines.java
+++ b/src/main/java/org/nrg/xnat/restlet/actions/TriggerPipelines.java
@@ -64,7 +64,7 @@ public class TriggerPipelines implements Callable<Boolean> {
         xnatPipelineLauncher.setParameter("userfullname", XnatPipelineLauncher.getUserName(user));
         xnatPipelineLauncher.setParameter("adminemail", XDAT.getSiteConfigPreferences().getAdminEmail());
         xnatPipelineLauncher.setParameter("xnatserver", TurbineUtils.GetSystemName());
-        xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
+        xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().getHostname());
         xnatPipelineLauncher.setParameter("sessionType", expt.getXSIType());
         xnatPipelineLauncher.setParameter("xnat_project", expt.getProject());
 
diff --git a/src/main/java/org/nrg/xnat/restlet/resources/ProjtExptPipelineResource.java b/src/main/java/org/nrg/xnat/restlet/resources/ProjtExptPipelineResource.java
index a3cf5b56..d2d064b1 100644
--- a/src/main/java/org/nrg/xnat/restlet/resources/ProjtExptPipelineResource.java
+++ b/src/main/java/org/nrg/xnat/restlet/resources/ProjtExptPipelineResource.java
@@ -279,7 +279,7 @@ public class ProjtExptPipelineResource extends SecureResource {
         hasParams.add("userfullname");
         xnatPipelineLauncher.setParameter("adminemail", XDAT.getSiteConfigPreferences().getAdminEmail());
         hasParams.add("adminemail");
-        xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
+        xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().getHostname());
         hasParams.add("mailhost");
         xnatPipelineLauncher.setParameter("xnatserver", TurbineUtils.GetSystemName());
         hasParams.add("xnatserver");
@@ -394,7 +394,7 @@ public class ProjtExptPipelineResource extends SecureResource {
         xnatPipelineLauncher.setParameter("useremail", user.getEmail());
 	    xnatPipelineLauncher.setParameter("userfullname", XnatPipelineLauncher.getUserName(user));
 	    xnatPipelineLauncher.setParameter("adminemail", XDAT.getSiteConfigPreferences().getAdminEmail());
-	    xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
+	    xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().getHostname());
 	    xnatPipelineLauncher.setParameter("xnatserver", TurbineUtils.GetSystemName());
 
 
diff --git a/src/main/java/org/nrg/xnat/turbine/modules/actions/ManagePipeline.java b/src/main/java/org/nrg/xnat/turbine/modules/actions/ManagePipeline.java
index 74253496..7dd6b042 100644
--- a/src/main/java/org/nrg/xnat/turbine/modules/actions/ManagePipeline.java
+++ b/src/main/java/org/nrg/xnat/turbine/modules/actions/ManagePipeline.java
@@ -379,7 +379,7 @@ public class ManagePipeline extends SecureAction {
             xnatPipelineLauncher.setParameter("useremail", user.getEmail());
             xnatPipelineLauncher.setParameter("userfullname", XnatPipelineLauncher.getUserName(user));
             xnatPipelineLauncher.setParameter("adminemail", XDAT.getSiteConfigPreferences().getAdminEmail());
-            xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
+            xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().getHostname());
             xnatPipelineLauncher.setParameter("xnatserver", TurbineUtils.GetSystemName());
             xnatPipelineLauncher.setPipelineName(pipeline_path);
             String exptLabel = item.getStringProperty("label");
diff --git a/src/main/java/org/nrg/xnat/turbine/modules/actions/PipelineActions.java b/src/main/java/org/nrg/xnat/turbine/modules/actions/PipelineActions.java
index 46433009..208a02ea 100644
--- a/src/main/java/org/nrg/xnat/turbine/modules/actions/PipelineActions.java
+++ b/src/main/java/org/nrg/xnat/turbine/modules/actions/PipelineActions.java
@@ -204,7 +204,7 @@ public class PipelineActions extends SecureAction{
         xnatPipelineLauncher.setParameter("userfullname", XnatPipelineLauncher.getUserName(user));
         xnatPipelineLauncher.setParameter("adminemail", XDAT.getSiteConfigPreferences().getAdminEmail());
         xnatPipelineLauncher.setParameter("xnatserver", TurbineUtils.GetSystemName());
-        xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
+        xnatPipelineLauncher.setParameter("mailhost", XDAT.getNotificationsPreferences().getSmtpServer().getHostname());
 
         String emailsStr =  ((String)org.nrg.xdat.turbine.utils.TurbineUtils.GetPassedParameter("emailField",data));
         if (emailsStr != null) {
diff --git a/src/main/java/org/nrg/xnat/turbine/modules/actions/QDECAction.java b/src/main/java/org/nrg/xnat/turbine/modules/actions/QDECAction.java
index d753fc8f..0888c646 100644
--- a/src/main/java/org/nrg/xnat/turbine/modules/actions/QDECAction.java
+++ b/src/main/java/org/nrg/xnat/turbine/modules/actions/QDECAction.java
@@ -208,7 +208,7 @@ public class QDECAction extends ListingAction{
         
         param = parameters.addNewParameter();
         param.setName("mailhost");
-        param.addNewValues().setUnique( XDAT.getNotificationsPreferences().getSmtpServer().get("host"));
+        param.addNewValues().setUnique( XDAT.getNotificationsPreferences().getSmtpServer().getHostname());
         
         return parameters;
         
diff --git a/src/main/java/org/nrg/xnat/turbine/utils/ArcSpecManager.java b/src/main/java/org/nrg/xnat/turbine/utils/ArcSpecManager.java
index a5a704ab..2f9bdc18 100644
--- a/src/main/java/org/nrg/xnat/turbine/utils/ArcSpecManager.java
+++ b/src/main/java/org/nrg/xnat/turbine/utils/ArcSpecManager.java
@@ -15,6 +15,7 @@ import org.nrg.xdat.model.ArcProjectI;
 import org.nrg.xdat.om.ArcArchivespecification;
 import org.nrg.xdat.preferences.NotificationsPreferences;
 import org.nrg.xdat.preferences.SiteConfigPreferences;
+import org.nrg.xdat.preferences.SmtpServer;
 import org.nrg.xft.event.EventDetails;
 import org.nrg.xft.event.EventUtils;
 import org.nrg.xft.security.UserI;
@@ -31,7 +32,6 @@ import java.io.IOException;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author timo
@@ -65,7 +65,9 @@ public class ArcSpecManager {
                     String cachePath = arcSpec.getGlobalCachePath();
                     if (cachePath!=null){
                         File f = new File(cachePath,"archive_specification.xml");
-                        f.getParentFile().mkdirs();
+                        if (!f.getParentFile().mkdirs()) {
+                            throw new RuntimeException("Failed to create working file " + f.getAbsolutePath() + ", please check permissions and file system.");
+                        }
                         FileWriter fw = new FileWriter(f);
 
                         arcSpec.toXML(fw, true);
@@ -120,12 +122,11 @@ public class ArcSpecManager {
             arcSpec.setSiteUrl(siteConfigPreferences.getSiteUrl());
         }
 
-        final Map<String, String> smtpServer = notificationsPreferences.getSmtpServer();
-        if (smtpServer != null && smtpServer.containsKey("host")) {
-            if (logger.isInfoEnabled()) {
-                logger.info("Setting SMTP host to: {}", smtpServer.get("host"));
-            }
-            arcSpec.setSmtpHost(smtpServer.get("host"));
+        final SmtpServer smtpServer = notificationsPreferences.getSmtpServer();
+        if (smtpServer != null) {
+            final String hostname = smtpServer.getHostname();
+            logger.info("Setting SMTP host to: {}", hostname);
+            arcSpec.setSmtpHost(hostname);
         }
 
         if (logger.isInfoEnabled()) {
diff --git a/src/main/java/org/nrg/xnat/utils/XnatUserProvider.java b/src/main/java/org/nrg/xnat/utils/XnatUserProvider.java
index 0314d6fa..ad38c9ab 100644
--- a/src/main/java/org/nrg/xnat/utils/XnatUserProvider.java
+++ b/src/main/java/org/nrg/xnat/utils/XnatUserProvider.java
@@ -9,6 +9,7 @@
 
 package org.nrg.xnat.utils;
 
+import org.apache.commons.lang3.StringUtils;
 import org.nrg.framework.exceptions.NrgServiceError;
 import org.nrg.framework.exceptions.NrgServiceRuntimeException;
 import org.nrg.xdat.security.helpers.Users;
@@ -27,7 +28,8 @@ import javax.inject.Provider;
 @Component
 public class XnatUserProvider implements Provider<UserI> {
     public XnatUserProvider(final String login) {
-        _login = login;
+        _logger.debug("Initializing user provider with login {}", login);
+        setLogin(login);
     }
 
     /**
@@ -35,16 +37,17 @@ public class XnatUserProvider implements Provider<UserI> {
      */
     @Override
     public UserI get() {
-        if (null == user) {
+        if (null == _user) {
             try {
-                user = Users.getUser(_login);
+                _user = Users.getUser(_login);
+                _logger.debug("Retrieved user with login {}", _login);
             } catch (UserInitException e) {
                 throw new NrgServiceRuntimeException(NrgServiceError.UserServiceError, "User object for name " + _login + " could not be initialized.");
             } catch (UserNotFoundException e) {
                 throw new NrgServiceRuntimeException(NrgServiceError.UserNotFoundError, "User with name " + _login + " could not be found.");
             }
         }
-        return user;
+        return _user;
     }
 
     /**
@@ -57,7 +60,20 @@ public class XnatUserProvider implements Provider<UserI> {
         return _login;
     }
 
+    /**
+     * Sets the configured login name for the default user.
+     *
+     * @param login    The user login name to configure.
+     */
+    public void setLogin(final String login) {
+        if (!StringUtils.equals(_login, login)) {
+            _login = login;
+            _user = null;
+        }
+    }
+
     private final Logger _logger = LoggerFactory.getLogger(XnatUserProvider.class);
-    private final String _login;
-    private UserI user = null;
+
+    private String _login;
+    private UserI _user = null;
 }
diff --git a/src/main/resources/META-INF/xnat/preferences/site-config.properties b/src/main/resources/META-INF/xnat/preferences/site-config.properties
deleted file mode 100644
index 0539c38c..00000000
--- a/src/main/resources/META-INF/xnat/preferences/site-config.properties
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# web: site-config.properties
-# XNAT http://www.xnat.org
-# Copyright (c) 2016, Washington University School of Medicine and Howard Hughes Medical Institute
-# All Rights Reserved
-#
-# Released under the Simplified BSD.
-#
-
-# The XNAT siteConfiguration.properties is only used as the default site-wide configuration when a
-# configuration is not already stored in the configuration service. After system initialization, the
-# contents of this file can be used to add new properties to the system, but not to change the values
-# of existing properties. For that, you should only modify site properties using the standard administrative
-# interface.
-checksums=true
-#checksums.property.changed.listener=org.nrg.xnat.utils.ChecksumsSiteConfigurationListener
-#showapplet=false
-enableDicomReceiver=true
-enableDicomReceiver.property.changed.listener=org.nrg.dcm.DicomSCPSiteConfigurationListener
-emailVerification=true
-enableProjectAppletScript=false
-displayNameForGenericImageSession.singular=Session
-displayNameForGenericImageSession.plural=Sessions
-UI.debug-extension-points=false
-UI.allow-advanced-search=true
-UI.allow-new-user-comments=true
-UI.allow-scan-addition=true
-UI.show-left-bar=true
-UI.show-left-bar-projects=true
-UI.show-left-bar-favorites=true
-UI.show-left-bar-search=true
-UI.show-left-bar-browse=true
-UI.show-manage-files=true
-UI.allow-non-admin-project-creation=true
-UI.login_failure_message=Your login attempt failed because the username and password combination you provided was invalid or your user already has the maximum number of user sessions open. After %d failed login attempts, your user account will be locked. If you believe your account is currently locked, you can:<ul><li>Unlock it by resetting your password</li><li>Wait one hour for it to unlock automatically</li></ul>
-
-# Indicates whether access to the list of system users should be restricted to site administrators only.
-restrictUserListAccessToAdmins=false
-
-UI.allow-blocked-subject-assessor-view=false
-
-files.zip_extensions=zip,jar,rar,ear,gar,mrb
-
-emailAllowNonuserSubscribers=true
-
-requireSaltedPasswords=false
-
-siteDescriptionType=Page
-siteDescriptionPage=/screens/site_description.vm
-siteDescriptionText=SITE DESCRIPTION HERE: Go to Administer -> Configuration -> Site Information to change.
-siteLoginLanding=/screens/QuickSearch.vm
-siteLandingLayout=/Index.vm
-siteHome=/screens/QuickSearch.vm
-siteHomeLayout=/Index.vm
-
-scanTypeMapping=true
-
-passwordExpirationType=Interval
-# Interval, in days, for expiring unchanged passwords (0 disables feature). Uses PostgreSQL interval notation: http://www.postgresql.org/docs/9.0/static/functions-datetime.html
-passwordExpirationInterval=1 year
-# Date for expiring passwords. Generally null by default.
-passwordExpirationDate=
\ No newline at end of file
diff --git a/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml
index ec8e5b88..81c14af4 100644
--- a/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml
+++ b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml
@@ -308,7 +308,7 @@ generalSecuritySettings:
     contents:
         securityChannel:
             kind: panel.select.single
-            name: ":security.channel"
+            name: ":securityChannel"
             label: Security Channel
             options:
                 any: Any
@@ -332,7 +332,7 @@ generalSecuritySettings:
             description: "Should this site restrict access to the list of system users to site administrators only? If turned on, the site is more secure, but this restricts project owners from being able to administer users in their projects directly."
         uiAllowNonAdminProjectCreation:
             kind: panel.input.switchbox
-            name: ":UI.allow-non-admin-project-creation"
+            name: ":uiAllowNonAdminProjectCreation"
             label: "Allow non-administrators <br>to create projects?"
             onText: Allow
             offText: Do Not Allow
@@ -384,17 +384,17 @@ userLoginsSessionControls:
 #            description: Allow user to resume where they left off, if logging back in after a session timeout?
         maximumConcurrentSessions:
             kind: panel.input.number
-            name: ":sessions.concurrent_max"
+            name: ":concurrentMaxSessions"
             label: Maximum Concurrent Sessions
             validation: integer gte:1 onblur
             description: The maximum number of permitted sessions a user can have open simultaneously. You must restart Tomcat for changes to this to take effect.
         loginFailureMessage:
             kind: panel.textarea
-            name: ":UI.login_failure_message"
+            name: ":uiLoginFailureMessage"
             label: Login Failure Message
             code: html
             description: Text to show when a user fails to login
-#            value: "?? XNAT:data:siteConfig:UI.login_failure_message"
+#            value: "?? XNAT:data:siteConfig:uiLoginFailureMessage"
         maximumFailedLogins:
             kind: panel.input.number
             name: maxFailedLogins
@@ -559,25 +559,25 @@ securityServices:
         securityServicesFeatureDefault:
             kind: panel.input.text
 #            id: securityServicesFeatureDefault
-            name: ":security.services.feature.default"
+            name: ":featureService"
             label: Feature Default
             size: 50
         securityServicesFeatureRepoDefault:
             kind: panel.input.text
 #            id: securityServicesFeatureRepoDefault
-            name: ":security.services.featureRepository.default"
+            name: ":featureRepositoryService"
             label: Feature Repository Default
             size: 50
         securityServicesRoleDefault:
             kind: panel.input.text
 #            id: securityServicesRoleDefault
-            name: ":security.services.role.default"
+            name: ":roleService"
             label: Role Default
             size: 50
         securityServicesRoleRepositoryDefault:
             kind: panel.input.text
 #            id: securityServicesRoleRepositoryDefault
-            name: ":security.services.roleRepository.default"
+            name: ":roleRepositoryService"
             label: Role Repository Default
             size: 50
 
@@ -591,33 +591,33 @@ emailServerSettings:
     contents:
         smtpEnabled:
             kind: panel.input.switchbox
-            name: ":smtp.enabled"
+            name: ":smtpEnabled"
             label: "Enable SMTP?"
             onText: Enabled
             offText: Disabled
         hostname:
             kind: panel.input.text
-            name: host
+            name: smtpHostname
             label: Host
             placeholder: localhost
         port:
             kind: panel.input.number
-            name: port
+            name: smtpPort
             label: Port
             validation: allow-empty integer onblur
             placeholder: 587
         username:
             kind: panel.input.text
-            name: username
+            name: smtpUsername
             label: Username
             placeholder: name@host.org
         password:
             kind: panel.input.password
-            name: password
+            name: smtpPassword
             label: Password
         protocol:
             kind: panel.input.text
-            name: protocol
+            name: smtpProtocol
             label: Protocol
             placeholder: smtp
         # subhead breaks up panel items
@@ -627,19 +627,19 @@ emailServerSettings:
             label: Properties
         smtpAuth:
             kind: panel.input.switchbox
-            name: ":mail.smtp.auth"
+            name: ":smtpAuth"
             label: SMTP Auth?
             onText: Enabled
             offText: Disabled
         smtpStartTls:
             kind: panel.input.switchbox
-            name: ":mail.smtp.starttls.enable"
+            name: ":smtpStartTls"
             label: Start TLS?
             onText: Enabled
             offText: Disabled
-        smtpSSLTrust:
+        smtpSslTrust:
             kind: panel.input.text
-            name: ":mail.smtp.ssl.trust"
+            name: ":smtpSslTrust"
             label: SSL Trust
             placeholder: localhost
         emailPrefix:
@@ -1000,7 +1000,7 @@ registrationOptions:
                 when a user registers.
         uiAllowNewUserComments:
             kind: panel.input.switchbox
-            name: ":UI.allow-new-user-comments"
+            name: ":uiAllowNewUserComments"
             label: "Allow User Comments <br>on Registration?"
             onText: Allow
             offText: Do Not Allow
@@ -1015,11 +1015,11 @@ manageDataTypes:
     contents:
         displayNameForGenericImageSessionSingular:
             kind: panel.input.text
-            name: ":displayNameForGenericImageSession.singular"
+            name: ":imageSessionDisplayNameSingular"
             label: "Singular Display Name For Generic Image Session Singular"
         displayNameForGenericImageSessionPlural:
             kind: panel.input.text
-            name: ":displayNameForGenericImageSession.plural"
+            name: ":imageSessionDisplayNamePlural"
             label: "Plural Display Name For Generic Image Session Singular"
 
 sessionBuilder:
@@ -1030,6 +1030,15 @@ sessionBuilder:
     contentType: json
     url: /xapi/siteConfig
     contents:
+        receivedFileUser:
+            kind: panel.input.text
+            name: receivedFileUser
+            label: Received File User
+            validation: id-strict max-length:40 onblur
+            placeholder: User account for performing import and archiving operations
+            description: >
+                This should be the login name of an enabled and valid user. The specified user must be a site
+                administrator.
         sessionXmlRebuilderRepeat:
             kind: panel.input.number
             name: sessionXmlRebuilderRepeat
diff --git a/src/main/webapp/WEB-INF/conf/services.properties b/src/main/webapp/WEB-INF/conf/services.properties
deleted file mode 100644
index 429b50d9..00000000
--- a/src/main/webapp/WEB-INF/conf/services.properties
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# D:/Development/XNAT/1.6/xnat_builder_1_6dev/plugin-resources/conf/services.properties
-# XNAT http://www.xnat.org
-# Copyright (c) 2014, Washington University School of Medicine
-# All Rights Reserved
-#
-# Released under the Simplified BSD.
-#
-# Last modified 2/7/14 12:19 PM
-#
-site.title=XNAT
-
-datasource.name=xnat
-datasource.driver=org.postgresql.Driver
-datasource.url=jdbc:postgresql://localhost/xnat
-datasource.username=xnat
-datasource.password=xnat
-
-hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
-hibernate.hbm2ddl.auto=update
-hibernate.show_sql=false
-hibernate.cache.use_second_level_cache=true
-hibernate.cache.use_query_cache=true
-
-mailserver.host=mail.server
-mailserver.port=25
-mailserver.username=
-mailserver.password=
-mailserver.protocol=smtp
-mailserver.admin=jrherrick@wustl.edu
-mailserver.prefix=XNAT
-
-# Session XML rebuilder settings. interval is in minutes, repeat is in milliseconds.
-services.rebuilder.interval=5
-services.rebuilder.repeat=60000
-
-# Settings for the DICOM SCP Receiver. You can change the AE title and port here, as well as change the user that is
-# used for operations on received files, e.g. archiving sessions in projects with auto-archiving.
-services.dicom.scp.aetitle=XNAT
-services.dicom.scp.port=8104
-services.dicom.scp.receivedfileuser=admin
-
-# Indicate the required security channel for the server. This can be http, https, or any.
-security.channel=any
-
-# Number of failed login attempts before accounts are temporarily locked (-1 disables feature).
-security.max_failed_logins=-1
-# Number of milliseconds to lock user accounts that have exceeded the max_failed_logins count (3600000 for 1 hour, 86400000 for 24 hours).
-security.max_failed_logins_lockout_duration=86400000
-# Number of seconds of inactivity before an account is disabled (31556926 for 1 year).
-security.inactivity_before_lockout=31556926
-
-# Interval for timing out alias tokens. Uses PostgreSQL interval notation: http://www.postgresql.org/docs/9.0/static/functions-datetime.html
-security.token_timeout=2 days
-
-# Java regular expression that new passwords must match. For no complexity checks, set this to ^.*$
-security.password_complexity=^.*$
-# Message that explains the password complexity requirements. This is displayed when user chooses a new password that fails to meet them.
-security.password_complexity_message=Password is not sufficiently complex.
-
-# Number of days for which a password cannot be reused.
-security.password_history=365
-
-# The maximum number of permitted sessions a user can have open simultaneously.
-security.sessions.concurrent_max=1000
-
-# The following parameters are used to allow/force users to enter change justifications when modifying data.
-audit.require_change_justification=false
-audit.show_change_justification=false
-
-# Sets default values for the ActiveMQ configuration.
-amq.usage.temp=128mb
-amq.usage.mem=512mb
-amq.usage.store=1gb
-
-# Comma-separated list of the providers that users will be able to use to authenticate.
-provider.providers.enabled=db
-
-provider.db.name=Database
-provider.db.id=localdb
-provider.db.type=db
-
-# Add "ldap1" to the enabled provider list above and fill in the missing fields to enable LDAP authentication.
-provider.ldap1.name=LDAP
-provider.ldap1.id=ldap1
-provider.ldap1.type=ldap
-provider.ldap1.address=
-provider.ldap1.userdn=
-provider.ldap1.password=
-provider.ldap1.search.base=
-provider.ldap1.search.filter=
diff --git a/src/main/webapp/resources/samples/prefs-init.ini b/src/main/webapp/resources/samples/prefs-init.ini
new file mode 100644
index 00000000..333765e7
--- /dev/null
+++ b/src/main/webapp/resources/samples/prefs-init.ini
@@ -0,0 +1,30 @@
+#
+# prefs-init.ini
+# XNAT http://www.xnat.org
+# Copyright (c) 2016, Washington University School of Medicine
+# All Rights Reserved
+#
+# Released under the Simplified BSD.
+#
+
+[siteConfig]
+siteUrl=http://xnat-centos.xnat.org
+adminEmail=jrherrick@wustl.edu
+archivePath=/data/xnat/archive
+buildPath=/data/xnat/build
+cachePath=/data/xnat/cache
+ftpPath=/data/xnat/ftp
+pipelinePath=/data/xnat/pipeline
+prearchivePath=/data/xnat/prearchive
+initialized=true
+
+[notifications]
+hostname=smtp.gmail.com
+username=foo@gmail.com
+password=password1234
+port=587
+protocol=smtp
+smtpAuth=true
+smtpStartTls=true
+
+
diff --git a/src/main/webapp/WEB-INF/conf/xnat-conf.properties b/src/main/webapp/resources/samples/xnat-conf.properties
similarity index 100%
rename from src/main/webapp/WEB-INF/conf/xnat-conf.properties
rename to src/main/webapp/resources/samples/xnat-conf.properties
diff --git a/src/main/webapp/scripts/project/settingsTabMgmt.js b/src/main/webapp/scripts/project/settingsTabMgmt.js
index c13ccc0a..bbc6bd69 100644
--- a/src/main/webapp/scripts/project/settingsTabMgmt.js
+++ b/src/main/webapp/scripts/project/settingsTabMgmt.js
@@ -60,8 +60,8 @@ function fullConfigHandler() {
     };
 
     var data = buildSettingsUpdateRequestBody([
-        'siteId','UI.debug-extension-points', 'siteDescriptionType', 'siteDescriptionText', 'siteDescriptionPage', 'siteUrl', 'siteAdminEmail', 'siteLoginLanding', 'siteLandingLayout', 'siteHome', 'siteHomeLayout'
-        , 'enableCsrfToken', 'enableCsrfEmail', 'restrictUserListAccessToAdmins', 'UI.allow-non-admin-project-creation', 'requireSaltedPasswords', 'passwordExpirationType', 'passwordExpirationInterval', 'passwordExpirationDate'
+        'siteId','uiDebugExtensionPoints', 'siteDescriptionType', 'siteDescriptionText', 'siteDescriptionPage', 'siteUrl', 'siteAdminEmail', 'siteLoginLanding', 'siteLandingLayout', 'siteHome', 'siteHomeLayout'
+        , 'enableCsrfToken', 'enableCsrfEmail', 'restrictUserListAccessToAdmins', 'uiAllowNonAdminProjectCreation', 'requireSaltedPasswords', 'passwordExpirationType', 'passwordExpirationInterval', 'passwordExpirationDate'
         , 'archivePath', 'checksums', 'prearchivePath', 'cachePath', 'ftpPath', 'buildPath', 'pipelinePath'
         , 'requireLogin', 'enableNewRegistrations', 'emailVerification'
         , 'error', 'issue', 'newUser', 'update', 'emailAllowNonuserSubscribers', 'smt.enabled'
diff --git a/src/main/webapp/setup/site-setup.yaml b/src/main/webapp/setup/site-setup.yaml
index ea6d480c..516b6db2 100644
--- a/src/main/webapp/setup/site-setup.yaml
+++ b/src/main/webapp/setup/site-setup.yaml
@@ -175,31 +175,31 @@ siteSetup:
 
                 host:
                     kind: panel.input.text
-                    name: host
+                    name: smtpHostname
                     label: Host
                     placeholder: localhost
                     validation: required
 
                 port:
                     kind: panel.input.number
-                    name: port
+                    name: smtpPort
                     label: Port
                     placeholder: 25
                     validation: required number
 
                 username:
                     kind: panel.input.text
-                    name: username
+                    name: smtpUsername
                     label: Username
 
                 password:
                     kind: panel.input.password
-                    name: password
+                    name: smtpPassword
                     label: Password
 
                 protocol:
                     kind: panel.input.text
-                    name: protocol
+                    name: smtpProtocol
                     label: Protocol
 
                 mailServerProperties:
@@ -208,21 +208,21 @@ siteSetup:
 
                 smtpAuth:
                     kind: panel.input.switchbox
-                    name: mail.smtp.auth
+                    name: smtpAuth
                     label: SMTP Auth?
                     onText: Enabled
                     offText: Disabled
 
                 smtpStartTls:
                     kind: panel.input.switchbox
-                    name: mail.smtp.starttls.enable
+                    name: smtpStartTls
                     label: Start TLS?
                     onText: Enabled
                     offText: Disabled
 
-                smtpSSLTrust:
+                smtpSslTrust:
                     kind: panel.input.text
-                    name: mail.smtp.ssl.trust
+                    name: smtpSslTrust
                     label: SSL Trust
 
         # =========================
diff --git a/src/main/webapp/xdat-templates/layouts/Default.vm b/src/main/webapp/xdat-templates/layouts/Default.vm
index e19a8139..a1ebfd21 100644
--- a/src/main/webapp/xdat-templates/layouts/Default.vm
+++ b/src/main/webapp/xdat-templates/layouts/Default.vm
@@ -8,7 +8,7 @@ $navigation.setTemplate("/bodyOpen.vm")
 <!-- path: xdat-templates/layouts/Default -->
 
             $navigation.setTemplate("/DefaultTop.vm")
-        #if($turbineUtils.toBoolean($siteConfig.getProperty("UI.show-left-bar","true")))
+        #if($turbineUtils.toBoolean($siteConfig.getProperty("uiShowLeftBarBrowse","true")))
                 $navigation.setTemplate("/DefaultLeft.vm")
         #end
             $navigation.setTemplate("/Breadcrumb.vm")
diff --git a/src/main/webapp/xdat-templates/macros/TurbineMacros.vm b/src/main/webapp/xdat-templates/macros/TurbineMacros.vm
index 221f0065..fd5d4c70 100644
--- a/src/main/webapp/xdat-templates/macros/TurbineMacros.vm
+++ b/src/main/webapp/xdat-templates/macros/TurbineMacros.vm
@@ -1636,7 +1636,7 @@ $!turbineUtils.escapeJS($s)
 
 ##Used to load globally scoped VM files and inject them into parent VMs.
 #macro(addGlobalCustomScreenJS $subFolder)
-	#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.debug-extension-points","false")))document.write("<div class='extension_js'>/templates/screens/$subFolder</div>")#end
+	#if($turbineUtils.toBoolean($siteConfig.getProperty("uiDebugExtensionPoints","false")))document.write("<div class='extension_js'>/templates/screens/$subFolder</div>")#end
 	#foreach($screenProps in $turbineUtils.getTemplates($subFolder))
 		#set($templateFileName=$screenProps.getProperty("path"))
 		#if($user.isGuest())
@@ -1655,7 +1655,7 @@ $!turbineUtils.escapeJS($s)
 
 ##Used to load  VM files for specfic data-types and their extensions and inject them into parent VMs.
 #macro(addCustomScreenJS $dataType $subFolder)
-	#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.debug-extension-points","false")))document.write("<div class='extension_js'>/templates/screens/$dataType/$subFolder</div>")#end
+	#if($turbineUtils.toBoolean($siteConfig.getProperty("uiDebugExtensionPoints","false")))document.write("<div class='extension_js'>/templates/screens/$dataType/$subFolder</div>")#end
 	#foreach($screenProps in $turbineUtils.getTemplates($dataType,$subFolder))
 		#set($templateFileName=$screenProps.getProperty("path"))
 		#if($user.isGuest())
@@ -1674,7 +1674,7 @@ $!turbineUtils.escapeJS($s)
 
 ##Used to load globally scoped VM files and inject them into parent VMs.
 #macro(addGlobalCustomScreens $subFolder)
-	#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.debug-extension-points","false")))<div class="extension">/templates/screens/$subFolder</div>#end
+	#if($turbineUtils.toBoolean($siteConfig.getProperty("uiDebugExtensionPoints","false")))<div class="extension">/templates/screens/$subFolder</div>#end
 	#foreach($screenProps in $turbineUtils.getTemplates($subFolder))
 		#set($templateFileName=$screenProps.getProperty("path"))
 		#if($user.isGuest())
@@ -1693,7 +1693,7 @@ $!turbineUtils.escapeJS($s)
 
 ##Used to load  VM files for specfic data-types and their extensions and inject them into parent VMs.
 #macro(addCustomScreens $dataType $subFolder)
-	#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.debug-extension-points","false")))<div class="extension">/templates/screens/$dataType/$subFolder</div>#end
+	#if($turbineUtils.toBoolean($siteConfig.getProperty("uiDebugExtensionPoints","false")))<div class="extension">/templates/screens/$dataType/$subFolder</div>#end
 	#foreach($screenProps in $turbineUtils.getTemplates($dataType,$subFolder))
 		#set($templateFileName=$screenProps.getProperty("path"))
 		#if($user.isGuest())
diff --git a/src/main/webapp/xnat-templates/layouts/Index.vm b/src/main/webapp/xnat-templates/layouts/Index.vm
index d3f68965..32ca1920 100644
--- a/src/main/webapp/xnat-templates/layouts/Index.vm
+++ b/src/main/webapp/xnat-templates/layouts/Index.vm
@@ -9,7 +9,7 @@ $navigation.setTemplate("/bodyOpen.vm")
 
         $navigation.setTemplate("/DefaultTop.vm")
 
-        #if($turbineUtils.toBoolean($siteConfig.getProperty("UI.show-left-bar","true")))
+        #if($turbineUtils.toBoolean($siteConfig.getProperty("uiShowLeftBarBrowse","true")))
 
                 <!-- DefaultLeft -->
                 $navigation.setTemplate("/DefaultLeft.vm")
diff --git a/src/main/webapp/xnat-templates/navigations/HeaderIncludes.vm b/src/main/webapp/xnat-templates/navigations/HeaderIncludes.vm
index e5e68f2b..38c56789 100755
--- a/src/main/webapp/xnat-templates/navigations/HeaderIncludes.vm
+++ b/src/main/webapp/xnat-templates/navigations/HeaderIncludes.vm
@@ -89,11 +89,11 @@ $navigation.setTemplate("/BaseJS.vm")
     // 'page' object is same as 'context' - easier to remember?
     XNAT.data.page = XNAT.data.context;
 
-    XNAT.app.showLeftBar = $turbineUtils.toBoolean($siteConfig.getProperty("UI.show-left-bar","true"));
-    XNAT.app.showLeftBarProjects = $turbineUtils.toBoolean($siteConfig.getProperty("UI.show-left-bar-projects","true"));
-    XNAT.app.showLeftBarFavorites = $turbineUtils.toBoolean($siteConfig.getProperty("UI.show-left-bar-favorites","true"));
-    XNAT.app.showLeftBarSearch = $turbineUtils.toBoolean($siteConfig.getProperty("UI.show-left-bar-search","true"));
-    XNAT.app.showLeftBarBrowse = $turbineUtils.toBoolean($siteConfig.getProperty("UI.show-left-bar-browse","true"));
+    XNAT.app.showLeftBar = $turbineUtils.toBoolean($siteConfig.getProperty("uiShowLeftBarBrowse","true"));
+    XNAT.app.showLeftBarProjects = $turbineUtils.toBoolean($siteConfig.getProperty("uiShowLeftBarProjects","true"));
+    XNAT.app.showLeftBarFavorites = $turbineUtils.toBoolean($siteConfig.getProperty("uiShowLeftBarFavorites","true"));
+    XNAT.app.showLeftBarSearch = $turbineUtils.toBoolean($siteConfig.getProperty("uiShowLeftBarSearch","true"));
+    XNAT.app.showLeftBarBrowse = $turbineUtils.toBoolean($siteConfig.getProperty("uiShowLeftBarBrowse","true"));
 
     window.available_elements = [];
 
diff --git a/src/main/webapp/xnat-templates/navigations/XNATQuickSearch.vm b/src/main/webapp/xnat-templates/navigations/XNATQuickSearch.vm
index 41babb23..7b4bb5e8 100755
--- a/src/main/webapp/xnat-templates/navigations/XNATQuickSearch.vm
+++ b/src/main/webapp/xnat-templates/navigations/XNATQuickSearch.vm
@@ -42,7 +42,7 @@ function submitQuickSearch(){
 	</select>
 	<input id="searchValue" class="clean" name="searchValue" type="text" maxlength="40" size="20" value="$!field"/>
     <button type="button" id="search_btn" class="btn2" onclick="submitQuickSearch();">Go</button>
-#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-advanced-search","true")))
+#if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowAdvancedSearch","true")))
 
     <script>
 
diff --git a/src/main/webapp/xnat-templates/screens/xnat_ctSessionData/edit/scans.vm b/src/main/webapp/xnat-templates/screens/xnat_ctSessionData/edit/scans.vm
index 7e2e552f..9b9768c8 100644
--- a/src/main/webapp/xnat-templates/screens/xnat_ctSessionData/edit/scans.vm
+++ b/src/main/webapp/xnat-templates/screens/xnat_ctSessionData/edit/scans.vm
@@ -5,7 +5,7 @@
 #* @vtlvariable name="om" type="org.nrg.xdat.om.XnatCtsessiondata" *#
 #* @vtlvariable name="scan" type="org.nrg.xdat.om.XnatImagescandata" *#
 <!-- BEGIN /xnat-templates/screens/xnat_ctSessionData/edit/scans.vm -->
-#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-scan-addition","true")))
+#if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowScanAddition","true")))
 <DIV class="edit_header1" style="margin-bottom:16px">Scans &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 <input type="button" value="Add Scan" onclick="addScan(this)"/>
 </DIV>
@@ -112,7 +112,7 @@
   });
       
       
-#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-scan-addition","true")))
+#if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowScanAddition","true")))
   
   if(window.scanSet.scans.length==0){
     for(var newC=0;newC<5;newC++){
diff --git a/src/main/webapp/xnat-templates/screens/xnat_experimentData/actionsBox/ManageFiles.vm b/src/main/webapp/xnat-templates/screens/xnat_experimentData/actionsBox/ManageFiles.vm
index c3b4e331..dc6f1c4b 100644
--- a/src/main/webapp/xnat-templates/screens/xnat_experimentData/actionsBox/ManageFiles.vm
+++ b/src/main/webapp/xnat-templates/screens/xnat_experimentData/actionsBox/ManageFiles.vm
@@ -1,5 +1,5 @@
 <!-- Sequence: 5 -->
-#if($user.checkFeature($om,"manage_files") && $turbineUtils.toBoolean($siteConfig.getProperty("UI.show-manage-files","true")))
+#if($user.checkFeature($om,"manage_files") && $turbineUtils.toBoolean($siteConfig.getProperty("uiShowManageFiles","true")))
      <li class="yuimenuitem">
 			<A href="" ONCLICK="showFiles();return false;"><div class="ic">#if($actionObject.hasImage())<img border="0" src="$content.getURI("scripts/yui/build/treeview/assets/img/folders/cf.gif")"/>#else&nbsp;#end</div><div class="ic_spacer">&nbsp;</div>Manage Files</A>
 	 </li>
diff --git a/src/main/webapp/xnat-templates/screens/xnat_imageSessionData/edit/scans.vm b/src/main/webapp/xnat-templates/screens/xnat_imageSessionData/edit/scans.vm
index 88cbb22a..1f5ffacd 100644
--- a/src/main/webapp/xnat-templates/screens/xnat_imageSessionData/edit/scans.vm
+++ b/src/main/webapp/xnat-templates/screens/xnat_imageSessionData/edit/scans.vm
@@ -6,7 +6,7 @@ XNAT.app.scans={};
 </script>
 <DIV class="edit_header1" style="margin-bottom:16px">Scans &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 
-#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-scan-addition","true")))
+#if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowScanAddition","true")))
 <input type="button" value="Add Scan" onclick="addScan(this)"/>
 #end
 </DIV>
@@ -113,7 +113,7 @@ XNAT.app.scans={};
   });
       
       
-  #if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-scan-addition","true")))
+  #if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowScanAddition","true")))
       if(window.scanSet.scans.length==0){
         for(var newC=0;newC<5;newC++){
           var tempScan = window.classMapping.newInstance(getDefaultScanXSIType());
diff --git a/src/main/webapp/xnat-templates/screens/xnat_mrSessionData/edit/scans.vm b/src/main/webapp/xnat-templates/screens/xnat_mrSessionData/edit/scans.vm
index 81bfd64b..36029257 100644
--- a/src/main/webapp/xnat-templates/screens/xnat_mrSessionData/edit/scans.vm
+++ b/src/main/webapp/xnat-templates/screens/xnat_mrSessionData/edit/scans.vm
@@ -1,7 +1,7 @@
 #* @vtlvariable name="scan" type="org.nrg.xdat.om.XnatImagescandata" *#
 #* @vtlvariable name="user" type="org.nrg.xdat.security.XDATUser" *#
 <!-- BEGIN /xnat-templates/screens/xnat_mrSessionData/edit/scans.vm -->
-#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-scan-addition","true")))
+#if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowScanAddition","true")))
 <DIV class="edit_header1" style="margin-bottom:16px">Scans &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 <input type="button" value="Add Scan" onclick="addScan(this)"/>
 </DIV>
@@ -116,7 +116,7 @@
   });
 
 
-#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-scan-addition","true")))
+#if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowScanAddition","true")))
 
   if(window.scanSet.scans.length==0){
     for(var newC=0;newC<5;newC++){
diff --git a/src/main/webapp/xnat-templates/screens/xnat_petSessionData/edit/scans.vm b/src/main/webapp/xnat-templates/screens/xnat_petSessionData/edit/scans.vm
index 4e34b816..257f365c 100644
--- a/src/main/webapp/xnat-templates/screens/xnat_petSessionData/edit/scans.vm
+++ b/src/main/webapp/xnat-templates/screens/xnat_petSessionData/edit/scans.vm
@@ -7,7 +7,7 @@
 #end
 <DIV class="edit_header1" style="margin-bottom:16px">Scans &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 
-#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-scan-addition","true")))
+#if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowScanAddition","true")))
 <input type="button" value="Add Scan" onclick="addScan(this)"/>
 #end
 </DIV>
@@ -107,7 +107,7 @@
     listing.render();
   });
       
-  #if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-scan-addition","true")))
+  #if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowScanAddition","true")))
       if(window.scanSet.scans.length==0){
         for(var newC=0;newC<2;newC++){
           var tempScan = window.classMapping.newInstance("xnat:petScanData");
diff --git a/src/main/webapp/xnat-templates/screens/xnat_petmrSessionData/edit/scans.vm b/src/main/webapp/xnat-templates/screens/xnat_petmrSessionData/edit/scans.vm
index 63de28f4..4621cf1f 100644
--- a/src/main/webapp/xnat-templates/screens/xnat_petmrSessionData/edit/scans.vm
+++ b/src/main/webapp/xnat-templates/screens/xnat_petmrSessionData/edit/scans.vm
@@ -6,7 +6,7 @@
     #set($petscanTypes = $data.getSession().getAttribute("userHelper").getQueryResultsAsArrayList("select DISTINCT isd.type,isd.type from xnat_petscandata mr LEFT JOIN xnat_imagescandata isd ON mr.xnat_imagescandata_id=isd.xnat_imagescandata_id"))
 #end
 
-#if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-scan-addition","true")))
+#if($turbineUtils.toBoolean($siteConfig.getProperty("uiAllowScanAddition","true")))
 <DIV class="edit_header1" style="margin-bottom:16px">Scans &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
     <input type="button" value="Add Scan" onclick="addScan(this)"/>
 </DIV>
diff --git a/src/main/webapp/xnat-templates/screens/xnat_subjectData/actionsBox/ManageFiles.vm b/src/main/webapp/xnat-templates/screens/xnat_subjectData/actionsBox/ManageFiles.vm
index c3b4e331..dc6f1c4b 100644
--- a/src/main/webapp/xnat-templates/screens/xnat_subjectData/actionsBox/ManageFiles.vm
+++ b/src/main/webapp/xnat-templates/screens/xnat_subjectData/actionsBox/ManageFiles.vm
@@ -1,5 +1,5 @@
 <!-- Sequence: 5 -->
-#if($user.checkFeature($om,"manage_files") && $turbineUtils.toBoolean($siteConfig.getProperty("UI.show-manage-files","true")))
+#if($user.checkFeature($om,"manage_files") && $turbineUtils.toBoolean($siteConfig.getProperty("uiShowManageFiles","true")))
      <li class="yuimenuitem">
 			<A href="" ONCLICK="showFiles();return false;"><div class="ic">#if($actionObject.hasImage())<img border="0" src="$content.getURI("scripts/yui/build/treeview/assets/img/folders/cf.gif")"/>#else&nbsp;#end</div><div class="ic_spacer">&nbsp;</div>Manage Files</A>
 	 </li>
diff --git a/src/main/webapp/xnat-templates/screens/xnat_subjectData/xnat_subjectData_assessor.vm b/src/main/webapp/xnat-templates/screens/xnat_subjectData/xnat_subjectData_assessor.vm
index 667c20fc..e8a33334 100644
--- a/src/main/webapp/xnat-templates/screens/xnat_subjectData/xnat_subjectData_assessor.vm
+++ b/src/main/webapp/xnat-templates/screens/xnat_subjectData/xnat_subjectData_assessor.vm
@@ -2,8 +2,8 @@
 ##handles data that is not viewable by this user.  On some servers, users can see that these exist (but not view the actual data)
 ##on other servers, they shouldn't see that it exists at all.
 ##By default, the user shouldn't see these.
-##To allow, site administrators should configure the UI.allow-blocked-subject-assessor-view peroprty in siteConfiguration.properties
-    #if($turbineUtils.toBoolean($siteConfig.getProperty("UI.allow-blocked-subject-assessor-view","false")))
+##To allow, site administrators should configure the uiLoginFailureMessage peroprty in siteConfiguration.properties
+    #if($turbineUtils.toBoolean($siteConfig.getProperty("uiLoginFailureMessage","false")))
         #set($denied=true)
     <TR BGCOLOR="FF9999">
         <TD>$!assessor.getProperty("date")</TD>
-- 
GitLab