From 9b0f85b3e16ea145bc91bc3a658398ec5aaf50b8 Mon Sep 17 00:00:00 2001
From: Rick Herrick <jrherrick@wustl.edu>
Date: Sat, 28 May 2016 16:21:06 -0500
Subject: [PATCH] XNAT-4282 Delayed tag initialization until actually accessed
 to delay call to config service. Also fixed concurrent modification error in
 alias token scheduling.

---
 gradle/wrapper/gradle-wrapper.jar             | Bin 53639 -> 53556 bytes
 gradle/wrapper/gradle-wrapper.properties      |   4 +-
 gradlew                                       |  46 ++++----
 gradlew.bat                                   |   6 +-
 .../id/CompositeDicomObjectIdentifier.java    | 110 ++++++++++--------
 .../nrg/dcm/id/DbBackedProjectIdentifier.java |  67 ++++++-----
 .../dcm/id/Xnat15DicomProjectIdentifier.java  |  19 +--
 .../xnat/configuration/ApplicationConfig.java |  19 +--
 .../xnat/configuration/SchedulerConfig.java   |  54 +--------
 .../AliasTokenPreferenceHandlerMethod.java    |  18 ++-
 10 files changed, 156 insertions(+), 187 deletions(-)

diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 2c6137b87896c8f70315ae454e00a969ef5f6019..ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e 100644
GIT binary patch
delta 3268
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

delta 3282
zcmZWrc|6ox8~+(=7)xU;4bjMw#AKJH7ujVCQErIr$rk0NF$k|joT8AWON2r*DQg%E
z$r9bV*}_c{m8GI?uJ<=*ZoRM1`}^m4=6k;1=RD^*&pC5wH`$YaW5?QCvvcqw2oDcJ
zvI)t=%JZPc;z5_IVy4~^+*0^bI2-a`iX2KQ-@(o_PZXh9B{2<9Vw+-GssJVe1A#=2
zSqOx1mOy}t=fQD7WVgUej4;ZzaEO%(nBhPW33PfAn35I+1#~I$C71aKoU_Qr$vhu=
zRPS&0R#q2yFah6E;_$(|N`qFVf;;V%;~Ng10vCL=gSBXQeBqkedOLqQ{ji~K0$sed
zzdL$E@pH6xao@!e-<S{0v!@5X-iR1jc(w8Ut61Fnnj2jut^ACM3C>I-zoR@=TXRir
z<q8+xdzqvXjZ=~*JLkJBWhc3$afF%O-D25q6>gi5ep{wL=nP?aXu+6oqODWZy}dE3
zNkLUlq4Z-Ai6m?3NLNmDDhM*-4Zz<@?d8Ro+&a-<j@K}6C=*#rAEg?%CG8#Fio39o
z7TUi}T_Sv>YoR3bx|-ynf?k`#JgpVp7)G!H-deXS*sS9XSxPnsXRBO$E!y-8&3k1s
zmq;F}QH+}A)hbIoy4$%%T`lV6L*EV?J+0%u2bvlql^^=bYlXb_7t^?tIL{+nDdSYC
z7dXQkVtGLG0_DDHuen09SQc?Mx6agU1z)Qeu~Z^Kx9arwJ+dqHS=E&MaJyU7hw+7!
zE3T941r}YNI^^5NF0LW>b9%1#66YKzd|HY;tuG`v9M(w+vL5|hKNET4nU9lSRZ(eG
zZFk}c;XvWRaD3d!J3`gSF7+M>l~eb(od|E(nQFaK5wG&5K=gFcw~^wQns>V9bD_Vq
z+qfki4Snl<=JWBpFUzuP_-q}oOumaTv;J&-NUG83t@fR<2=Y*O+1Z@b-TTx$hl2wW
zbK=weXjz~9=V~&C!<@fOj1`rMMBe2%f6KGp*TsoPFOa&=g``fs*ApeEm;OF+cDS9_
zFW5W#-lElMdPLexiU9XnOLr+wcfi)S`;TiLNmIwkCHqJ295-SR4F|)dq$}1e7>tL-
z(>STZc(-#&1E<N7tzt?o&%zFcx3s@dYI(Y}r)7A_;Jkg9H6vrq(kSx1;C0HgFOM+I
zTdf7esAF@IDq^nrBX=*eo6A>wj;59`Yg%K;YTmP@>JsUu<1H4k)W{dLk1ZHMpL$hK
zYpxds<+ui4w`eA6-oz5iC-V>LeQ7#pbL_j+z?p<|<(7JR<dsD?xzeNz?N;4vp}UDR
z$4kn*M=Qm{L$dvZq+_qfbOr}j&Z@Q0G7E+HBB!WLrQ6bHilb}PzWo_Mw@j(z^pZ18
zkaRH%kW%^6j=Sbm|CQ5U$|M_Gb^q8dankj|rThBRS;8)l5B`ePw#v==`f<JRo9e6s
zTfTN&-pdqT0c{f51DNO!yi)0YB(E55nE7F9SC{kDy9~p`<wk`G>urnIMr$*iRCme5
zhuobPG8Me<U!@->XteydtMTwB6O9bhi;L?R^1!;>S`SZ}s?m*Gvy%r-c?i$1RgWha
zz6E)gKlT_TDr6VgsTN-ynIF{>sm)Z;!ase!DwJ19J9#$o3;Ev@#5zN><ai^G?p5(o
zk+HTd^?aE#ANjsse5-u?FHac}#hdd2UlK7b!~%koNuaRahnvj`C10%W+;BRV7OLL=
z>aSIYfmjV(X6#!(%=($9M@@7RjcE2nqie=`a{{*>;s`=r^6!#U##F3Uh10iVh6X+h
z#RT9@^Yd3;yAvzOFXooy_t%Aljg5C1jdfZ-wCm&6S)lCW{_6G2w%2e%)LiWS@v(6;
zg*~e)!}Ib6+lx-bwQ%_xv~Dd4<5eBLXcup5R~?F-)}Gkzmub9)H_>UIcAs8-?$BgK
zuD;6WIuvuG(fe3tMnrV`D0YK;)75HGdX_|;$EUF_%ouSOZg^o1OS|BpqpZ%)2^~Eh
zQ9kH6nXK|c$JTb7b-SuKbF<_+hn;z_%xgBJvMkmfK@eMz>tT#rJgDqQ(r_Tv(A2c*
z)HIwzqp)DnLv@Qd%DkGZA~6UQJ>|&FA#@UdVswj@FeOV;SArI~+ukQ&@cy9Sd&Qca
zCRvvZ&%c+SijqF7KcwQdoFjKcY2VBN&*)HWW}tf5b4<N)kDk6IWf}VbljF_*o*uNj
zKjD6b`Y|^r1;3d%Msb-y^C5$%=E><`srEfDvTb(0510v7?y~C$m)P;F+UHG-d+$L(
z-wKXsYVIi|&DSNm^Adj-#ks3CepN4-iN;m8__(X-e|kr9yt!5KiQKCm&2@{o>4L&G
z$J^hf2lHPh5t2XGz8-fPiVs`D*fG-o{+~ZEbeTZjOPL+DRA;Xg4ATLV-g6Lm;<Et(
zYQNtc%V`J%Y;edvSei$eStH3H(b_%?f{bz@h&Cvu?#%M%qE<xCviMh`_1FcNG-6E8
zkt|LGxsC-j@%StsKI(c*IVTKN9`}tEvo!v9ZivLDK4l>eX_c%v8|md+;ZQ~K5(_CP
znPfSXvN{epw6BVt9XkK2UStia-}{9X2T+YzoEHxUSx7~_6N|&v1lY063~SOOoXya-
zH~@+t8E$Hedup|?Emj^Wu%nLwAl0hz^HBiYTK6#<4rI5gLfhS{1ua{fA+*MAw$OsM
zQ_ym@AB5Jq-4)uJ_G8cr(_IBNKLS8B-5w4-rV}uGM8V!pJoru*mtnH{!{<}++z1jP
zfFSZ{(my^LrBxgf3&e52y@Ma>gE|Np2^k3A=#YR=Jqm@ZL&#oz8<=PCOEbe-Jb$or
z7=3-niX({PkC>>XQ7C}asSTxpodis-36$n{%ED}3_6wgWLieABW<%U0yJGv#wA|pY
zP7z2BlnJ~{V?z)Zb_CJcM2>WZ<N|Rl@NgCf0bTr1kmYSfkl;ZOYe59ru}N_LFcjFb
z@ql|>TOs-9;YNwFo5;^SK%s{m*uvnKVQx1(+bBU2O$A-;&yPm&^8|Z6w*fl_KeL;_
zF$RI{B#2>bhrjX|1WdjcxLhUyV!dGDAp8x56?_0CQWos%#zDxwn}ETcfY9Y`1qd~u
z5Z)h!c4hStVHR&?vCHOY2G-~a+WRvHX2IElP@W_>)*~y;On1MS{{{oy@MIi<7;GZu
zfTA8782)1q0aG7|%5*{g6MiUref)QYDKvHnD&4<HHVQ%?+d^5}W3)Yf1yeDK%#uS{
zez5yM8JgCu|J$RFU~jKEl>OREz%0ZA%PJyh=!J(94D=G%I>3CdC0v_Y@ZmZubZ!px
z*fS5-kB>&VmIlib{bVnURQZH}G0Q+9A|PdOfyF1R!f&APQZZ!i?_*WpvyXt8DM2B$
zfLx%ek2P%@iguTwdt$(BWEfJZpMarMp~<QITvJ_ZO~f@coeH#3H&-wj6!rg8K~xrV
z4~>r&{+=K+8eECVQ_(l?&{CY^LlFHR%RnuSGD3y<B@M7PxMqNW+5Qmp4VXjS9=v}%
zH#%h_`lwgiq+6<oy0Lm;FxkVJ#H@~I)c~F3@fHNp+eEf#g5>>uoS<oN2i%~amlaBs
R-b9`N-v`yWyjq#ye*j(f3~c}a

diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2c5610fc..972604ae 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Mar 14 17:41:56 CDT 2016
+#Sat May 28 14:49:32 CDT 2016
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip
diff --git a/gradlew b/gradlew
index 9d82f789..27309d92 100755
--- a/gradlew
+++ b/gradlew
@@ -6,12 +6,30 @@
 ##
 ##############################################################################
 
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
 
 APP_NAME="Gradle"
 APP_BASE_NAME=`basename "$0"`
 
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD="maximum"
 
@@ -30,6 +48,7 @@ die ( ) {
 cygwin=false
 msys=false
 darwin=false
+nonstop=false
 case "`uname`" in
   CYGWIN* )
     cygwin=true
@@ -40,26 +59,11 @@ case "`uname`" in
   MINGW* )
     msys=true
     ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
 esac
 
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
 # Determine the Java command to use to start the JVM.
@@ -85,7 +89,7 @@ location of your Java installation."
 fi
 
 # Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
     MAX_FD_LIMIT=`ulimit -H -n`
     if [ $? -eq 0 ] ; then
         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
diff --git a/gradlew.bat b/gradlew.bat
index 72d362da..f6d5974e 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -8,14 +8,14 @@
 @rem Set local scope for the variables with windows NT shell
 if "%OS%"=="Windows_NT" setlocal
 
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
 set DIRNAME=%~dp0
 if "%DIRNAME%" == "" set DIRNAME=.
 set APP_BASE_NAME=%~n0
 set APP_HOME=%DIRNAME%
 
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
 @rem Find java.exe
 if defined JAVA_HOME goto findJavaFromJavaHome
 
diff --git a/src/main/java/org/nrg/dcm/id/CompositeDicomObjectIdentifier.java b/src/main/java/org/nrg/dcm/id/CompositeDicomObjectIdentifier.java
index 4eb704ff..d571e350 100644
--- a/src/main/java/org/nrg/dcm/id/CompositeDicomObjectIdentifier.java
+++ b/src/main/java/org/nrg/dcm/id/CompositeDicomObjectIdentifier.java
@@ -10,10 +10,7 @@
  */
 package org.nrg.dcm.id;
 
-import java.util.regex.Pattern;
-
-import javax.inject.Provider;
-
+import com.google.common.collect.ImmutableSortedSet;
 import org.dcm4che2.data.DicomObject;
 import org.nrg.dcm.ChainExtractor;
 import org.nrg.dcm.Extractor;
@@ -22,67 +19,57 @@ import org.nrg.xft.security.UserI;
 import org.nrg.xnat.DicomObjectIdentifier;
 import org.nrg.xnat.Labels;
 
-import com.google.common.collect.ImmutableSortedSet;
-
-public class CompositeDicomObjectIdentifier implements
-DicomObjectIdentifier<XnatProjectdata> {
-    private final DicomProjectIdentifier projectID;
-    private final Extractor subjectExtractor, sessionExtractor, aaExtractor;
-    private final ImmutableSortedSet<Integer> tags;
+import javax.inject.Provider;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
 
-    public CompositeDicomObjectIdentifier(final DicomProjectIdentifier projectID,
-            final Extractor subjectExtractor,
-            final Extractor sessionExtractor,
-            final Extractor aaExtractor) {
-        this.projectID = projectID;
-        this.subjectExtractor = subjectExtractor;
-        this.sessionExtractor = sessionExtractor;
-        this.aaExtractor = aaExtractor;
-        
-        ImmutableSortedSet.Builder<Integer> builder = ImmutableSortedSet.naturalOrder();
-        builder.addAll(projectID.getTags());
-        builder.addAll(aaExtractor.getTags());
-        builder.addAll(sessionExtractor.getTags());
-        builder.addAll(subjectExtractor.getTags());
-        tags = builder.build();  
+public class CompositeDicomObjectIdentifier implements DicomObjectIdentifier<XnatProjectdata> {
+    public CompositeDicomObjectIdentifier(final DicomProjectIdentifier identifier,
+                                          final Extractor subjectExtractor,
+                                          final Extractor sessionExtractor,
+                                          final Extractor aaExtractor) {
+        _identifier = identifier;
+        _subjectExtractor = subjectExtractor;
+        _sessionExtractor = sessionExtractor;
+        _aaExtractor = aaExtractor;
     }
-    
-    public CompositeDicomObjectIdentifier(final DicomProjectIdentifier projectID,
-            final Iterable<Extractor> subjectExtractors,
-            final Iterable<Extractor> sessionExtractors,
-            final Iterable<Extractor> aaExtractors) {
-        this(projectID, new ChainExtractor(subjectExtractors),
-                new ChainExtractor(sessionExtractors), new ChainExtractor(aaExtractors));
+
+    public CompositeDicomObjectIdentifier(final DicomProjectIdentifier identifier,
+                                          final Iterable<Extractor> subjectExtractors,
+                                          final Iterable<Extractor> sessionExtractors,
+                                          final Iterable<Extractor> aaExtractors) {
+        this(identifier,
+             new ChainExtractor(subjectExtractors),
+             new ChainExtractor(sessionExtractors),
+             new ChainExtractor(aaExtractors));
     }
 
-    private UserI user = null;
-    private Provider<UserI> userProvider = null;
-    
     /*
      * (non-Javadoc)
      * @see org.nrg.xnat.DicomObjectIdentifier#getProject(org.dcm4che2.data.DicomObject)
      */
     public final XnatProjectdata getProject(final DicomObject o) {
-	if (null == user && null != userProvider) {
-	    user = userProvider.get();
-	}
-	return projectID.apply(user, o);
+        if (null == user && null != userProvider) {
+            user = userProvider.get();
+        }
+        return _identifier.apply(user, o);
     }
-    
+
     /*
      * (non-Javadoc)
      * @see org.nrg.xnat.DicomObjectIdentifier#getSessionLabel(org.dcm4che2.data.DicomObject)
      */
     public final String getSessionLabel(final DicomObject o) {
-        return Labels.toLabelChars(sessionExtractor.extract(o));
+        return Labels.toLabelChars(_sessionExtractor.extract(o));
     }
-    
+
     /*
      * (non-Javadoc)
      * @see org.nrg.xnat.DicomObjectIdentifier#getSubjectLabel(org.dcm4che2.data.DicomObject)
      */
     public final String getSubjectLabel(final DicomObject o) {
-        return Labels.toLabelChars(subjectExtractor.extract(o));
+        return Labels.toLabelChars(_subjectExtractor.extract(o));
     }
 
     /*
@@ -90,18 +77,18 @@ DicomObjectIdentifier<XnatProjectdata> {
      * @see org.nrg.xnat.DicomObjectIdentifier#getTags()
      */
     public final ImmutableSortedSet<Integer> getTags() {
-        return tags;
+        if (!_initialized) {
+            initialize();
+        }
+        return ImmutableSortedSet.copyOf(_tags);
     }
-    
-    private static final Pattern TRUE = Pattern.compile("t(?:rue)?", Pattern.CASE_INSENSITIVE);
-    private static final Pattern FALSE = Pattern.compile("f(?:alse)?", Pattern.CASE_INSENSITIVE);
 
     /*
      * (non-Javadoc)
      * @see org.nrg.xnat.DicomObjectIdentifier#requestsAutoarchive(org.dcm4che2.data.DicomObject)
      */
     public final Boolean requestsAutoarchive(DicomObject o) {
-        final String aa = aaExtractor.extract(o);
+        final String aa = _aaExtractor.extract(o);
         if (null == aa) {
             return null;
         } else if (TRUE.matcher(aa).matches()) {
@@ -112,12 +99,33 @@ DicomObjectIdentifier<XnatProjectdata> {
             return null;
         }
     }
-    
+
     public final void setUser(final UserI user) {
         this.user = user;
     }
-    
+
     public final void setUserProvider(final Provider<UserI> userProvider) {
         this.userProvider = userProvider;
     }
+
+    private void initialize() {
+        ImmutableSortedSet.Builder<Integer> builder = ImmutableSortedSet.naturalOrder();
+        builder.addAll(_identifier.getTags());
+        builder.addAll(_aaExtractor.getTags());
+        builder.addAll(_sessionExtractor.getTags());
+        builder.addAll(_subjectExtractor.getTags());
+        _tags.addAll(builder.build());
+        _initialized = true;
+    }
+
+    private static final Pattern TRUE  = Pattern.compile("t(?:rue)?", Pattern.CASE_INSENSITIVE);
+    private static final Pattern FALSE = Pattern.compile("f(?:alse)?", Pattern.CASE_INSENSITIVE);
+
+    private UserI           user         = null;
+    private Provider<UserI> userProvider = null;
+
+    private final DicomProjectIdentifier _identifier;
+    private final Extractor              _subjectExtractor, _sessionExtractor, _aaExtractor;
+    private final SortedSet<Integer> _tags        = new TreeSet<>();
+    private       boolean            _initialized = false;
 }
diff --git a/src/main/java/org/nrg/dcm/id/DbBackedProjectIdentifier.java b/src/main/java/org/nrg/dcm/id/DbBackedProjectIdentifier.java
index b2565608..2cac8622 100644
--- a/src/main/java/org/nrg/dcm/id/DbBackedProjectIdentifier.java
+++ b/src/main/java/org/nrg/dcm/id/DbBackedProjectIdentifier.java
@@ -10,11 +10,10 @@
 package org.nrg.dcm.id;
 
 
-import java.util.SortedSet;
-
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSortedSet;
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.Element;
-
 import org.dcm4che2.data.DicomObject;
 import org.nrg.xdat.om.XnatProjectdata;
 import org.nrg.xft.security.UserI;
@@ -23,27 +22,22 @@ import org.nrg.xnat.helpers.prearchive.PrearcUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.Lists;
-
-public class DbBackedProjectIdentifier implements DicomProjectIdentifier {
-    private final Logger logger = LoggerFactory.getLogger(DbBackedProjectIdentifier.class);
-    private final Iterable<DicomDerivedString> extractors;
-    private final ImmutableSortedSet<Integer> tags;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
-    public DbBackedProjectIdentifier(final Iterable<DicomDerivedString> identifiers) {
-        this.extractors = Lists.newArrayList(identifiers);
-        final ImmutableSortedSet.Builder<Integer> b = ImmutableSortedSet.naturalOrder();
-        for (final DicomObjectFunction f : identifiers) {
-            b.addAll(f.getTags());
-        }
-        tags = b.build();
+public abstract class DbBackedProjectIdentifier implements DicomProjectIdentifier {
+    public DbBackedProjectIdentifier() {
+        _log.debug("Creating DbBackedProjectIdentifier object with default constructor.");
     }
 
     public final XnatProjectdata apply(final UserI user, final DicomObject o) {
+        if (!_initialized) {
+            initialize();
+        }
         final Cache cache = GradualDicomImporter.getUserProjectCache(user);
-        for (final DicomDerivedString extractor : extractors) {
+        for (final DicomDerivedString extractor : _extractors) {
             final String alias = extractor.apply(o);
             if (!Strings.isNullOrEmpty(alias)) {
                 // added caching here to prevent duplicate project queries in every file transaction
@@ -51,31 +45,52 @@ public class DbBackedProjectIdentifier implements DicomProjectIdentifier {
                 final Element pe = cache.get(alias);
                 if (null == pe) {
                     // no cached value, look in the db
-                    final XnatProjectdata p = XnatProjectdata.getProjectByIDorAlias(alias.toString(), user, false);
-                    if (null != p && canCreateIn(user,p)) {
+                    final XnatProjectdata p = XnatProjectdata.getProjectByIDorAlias(alias, user, false);
+                    if (null != p && canCreateIn(user, p)) {
                         cache.put(new Element(alias, p));
                         return p;
                     } else {
                         // this alias is either not a project or not one we can write to
                         GradualDicomImporter.cacheNonWriteableProject(cache, alias);
-                    }                        
+                    }
                 } else if (!GradualDicomImporter.isCachedNotWriteableProject(pe)) {
-                    return (XnatProjectdata)pe.getObjectValue();
-                } // else cache returned no-such-writeable-project, so continue
+                    return (XnatProjectdata) pe.getObjectValue();
+                } // else cache returned no-such-writable-project, so continue
             }
         }
         return null;
     }
 
+    public SortedSet<Integer> getTags() {
+        if (!_initialized) {
+            initialize();
+        }
+        return ImmutableSortedSet.copyOf(_tags);
+    }
+
+    abstract protected List<DicomDerivedString> getIdentifiers();
+
+    private synchronized void initialize() {
+        _extractors.clear();
+        _tags.clear();
+        for (final DicomDerivedString function : getIdentifiers()) {
+            _extractors.add(function);
+            _tags.addAll(function.getTags());
+        }
+        _initialized = true;
+    }
 
     private boolean canCreateIn(final UserI user, final XnatProjectdata p) {
         try {
             return PrearcUtils.canModify(user, p.getId());
         } catch (Exception e) {
-            logger.error("Unable to check permissions for " + user + " in " + p, e);
+            _log.error("Unable to check permissions for " + user + " in " + p, e);
             return false;
         }
     }
 
-    public final SortedSet<Integer> getTags() { return tags; }
+    private final Logger                   _log         = LoggerFactory.getLogger(DbBackedProjectIdentifier.class);
+    private final List<DicomDerivedString> _extractors  = new ArrayList<>();
+    private final SortedSet<Integer>       _tags        = new TreeSet<>();
+    private       boolean                  _initialized = false;
 }
diff --git a/src/main/java/org/nrg/dcm/id/Xnat15DicomProjectIdentifier.java b/src/main/java/org/nrg/dcm/id/Xnat15DicomProjectIdentifier.java
index e770cfe9..b706a31d 100644
--- a/src/main/java/org/nrg/dcm/id/Xnat15DicomProjectIdentifier.java
+++ b/src/main/java/org/nrg/dcm/id/Xnat15DicomProjectIdentifier.java
@@ -28,15 +28,9 @@ import java.util.regex.Pattern;
 class Xnat15DicomProjectIdentifier extends DbBackedProjectIdentifier {
     private static final String DICOM_PROJECT_RULES = "dicom-project.rules";
 
-    Xnat15DicomProjectIdentifier() {
-        super(getIdentifiers());
-    }
-
-    private static Logger slog() {
-        return LoggerFactory.getLogger(Xnat15DicomProjectIdentifier.class);
-    }
+    private static final Logger _log = LoggerFactory.getLogger(Xnat15DicomProjectIdentifier.class);
 
-    private static List<DicomDerivedString> getIdentifiers() {
+    protected List<DicomDerivedString> getIdentifiers() {
         final List<DicomDerivedString> identifiers = Lists.newArrayList();
         identifiers.add(new ContainedAssignmentDicomIdentifier(Tag.PatientComments, "Project", Pattern.CASE_INSENSITIVE));
         identifiers.add(new ContainedAssignmentDicomIdentifier(Tag.StudyComments, "Project", Pattern.CASE_INSENSITIVE));
@@ -73,19 +67,16 @@ class Xnat15DicomProjectIdentifier extends DbBackedProjectIdentifier {
         } catch (FileNotFoundException ignored) {
             //
         } catch (IOException e) {
-            slog().error("An error occurred trying to open the DICOM project rules configuration", e);
+            _log.error("An error occurred trying to open the DICOM project rules configuration", e);
         }
     }
 
     private static final Pattern CUSTOM_RULE_PATTERN = Pattern.compile("\\((\\p{XDigit}{4})\\,(\\p{XDigit}{4})\\):(.+?)(?::(\\d+))?");
 
-
-    private static final DicomDerivedString parseRule(final String rule) {
+    private static DicomDerivedString parseRule(final String rule) {
         final Matcher matcher = CUSTOM_RULE_PATTERN.matcher(rule);
         if (matcher.matches()) {
-            final StringBuilder tagsb = new StringBuilder("0x");
-            tagsb.append(matcher.group(1)).append(matcher.group(2));
-            final int    tag      = Integer.decode(tagsb.toString());
+            final int    tag      = Integer.decode("0x" + matcher.group(1) + matcher.group(2));
             final String regexp   = matcher.group(3);
             final String groupIdx = matcher.group(4);
             final int    group    = null == groupIdx ? 1 : Integer.parseInt(groupIdx);
diff --git a/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java b/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java
index 8c458859..fc87250d 100644
--- a/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java
+++ b/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java
@@ -1,13 +1,14 @@
 package org.nrg.xnat.configuration;
 
-import org.apache.commons.lang.StringUtils;
 import org.nrg.config.exceptions.SiteConfigurationException;
 import org.nrg.framework.services.ContextService;
-import org.nrg.xdat.XDAT;
 import org.nrg.xdat.preferences.InitializerSiteConfiguration;
 import org.nrg.xdat.preferences.NotificationsPreferences;
 import org.nrg.xdat.preferences.SiteConfigPreferences;
-import org.nrg.xdat.security.*;
+import org.nrg.xdat.security.HistoricPasswordValidator;
+import org.nrg.xdat.security.PasswordValidatorChain;
+import org.nrg.xdat.security.RegExpValidator;
+import org.nrg.xdat.security.XDATUserMgmtServiceImpl;
 import org.nrg.xdat.security.services.UserManagementServiceI;
 import org.nrg.xdat.services.ThemeService;
 import org.nrg.xdat.services.impl.ThemeServiceImpl;
@@ -19,7 +20,10 @@ import org.nrg.xnat.utils.XnatUserProvider;
 import org.springframework.context.annotation.*;
 
 import javax.inject.Inject;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
 
 @Configuration
 @ComponentScan({"org.nrg.automation.repositories", "org.nrg.config.daos", "org.nrg.dcm.xnat", "org.nrg.dicomtools.filters",
@@ -79,9 +83,8 @@ public class ApplicationConfig {
     }
 
     @Bean
-    public PasswordValidatorChain validator(final RegExpValidator regExpValidator, final HistoricPasswordValidator historicPasswordValidator) {
+    public PasswordValidatorChain validator() {
         return new PasswordValidatorChain();
-
     }
 
     // MIGRATION: I'm not even sure this is used, but we need to do away with it in favor of prefs.
@@ -98,12 +101,12 @@ public class ApplicationConfig {
 
     @Bean
     public XnatRestletExtensions xnatRestletExtensions() {
-        return new XnatRestletExtensions(new HashSet<>(Arrays.asList(new String[]{"org.nrg.xnat.restlet.extensions"})));
+        return new XnatRestletExtensions(new HashSet<>(Arrays.asList(new String[] {"org.nrg.xnat.restlet.extensions"})));
     }
 
     @Bean
     public ImporterHandlerPackages importerHandlerPackages() {
-        return new ImporterHandlerPackages(new HashSet<>(Arrays.asList(new String[]{"org.nrg.xnat.restlet.actions", "org.nrg.xnat.archive"})));
+        return new ImporterHandlerPackages(new HashSet<>(Arrays.asList(new String[] {"org.nrg.xnat.restlet.actions", "org.nrg.xnat.archive"})));
     }
 
     @Inject
diff --git a/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java b/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java
index 72b7991a..f69f7691 100644
--- a/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java
+++ b/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java
@@ -9,11 +9,8 @@ import org.nrg.xdat.preferences.PreferenceEvent;
 import org.nrg.xnat.helpers.prearchive.SessionXMLRebuilder;
 import org.nrg.xnat.security.ResetEmailRequests;
 import org.nrg.xnat.utils.XnatUserProvider;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jms.core.JmsTemplate;
 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.SchedulingConfigurer;
@@ -28,48 +25,10 @@ import java.util.List;
 @Configuration
 @EnableScheduling
 public class SchedulerConfig implements SchedulingConfigurer {
-//    @Bean
-//    public TriggerTask disableInactiveUsers() throws SiteConfigurationException {
-//        try {
-//            final DisableInactiveUsers task = new DisableInactiveUsers(_preferences.getInactivityBeforeLockout(), (int) SiteConfigPreferences.convertPGIntervalToSeconds(_preferences.getMaxFailedLoginsLockoutDuration()));
-//            return new TriggerTask(task, new CronTrigger(_preferences.getInactivityBeforeLockoutSchedule()));
-//        } catch (SQLException e) {
-//            // This isn't a real thing: PGInterval doesn't actually access the database. But just to make everyone happy...
-//            throw new NrgServiceRuntimeException(NrgServiceError.Unknown, "This really shouldn't happen.", e);
-//        }
-//    }
-
-//    @Bean
-//    public TriggerTask resetFailedLogins() throws SiteConfigurationException {
-//        return new TriggerTask(new ResetFailedLogins(_template, _preferences.getMaxFailedLoginsLockoutDuration()), new PeriodicTrigger(900000));
-//    }
-
     @Bean
     public TriggerTask resetEmailRequests() {
         return new TriggerTask(new ResetEmailRequests(_emailRequestLogService), new PeriodicTrigger(900000));
     }
-//
-//    @Bean
-//    public TriggerTask clearExpiredAliasTokens() throws SiteConfigurationException {
-//        return new TriggerTask(new ClearExpiredAliasTokens(_template), new Trigger() {
-//            @Override public Date nextExecutionTime(TriggerContext triggerContext) {
-//                Calendar nextExecutionTime =  new GregorianCalendar();
-//                Date lastActualExecutionTime = triggerContext.lastActualExecutionTime();
-//                nextExecutionTime.setTime(lastActualExecutionTime != null ? lastActualExecutionTime : new Date());
-//                long expirationInterval = XDAT.getSiteConfigPreferences().getAliasTokenTimeout();
-//                if(expirationInterval<120){//Check every minute if interval is 2 hours or less
-//                    nextExecutionTime.add(Calendar.MINUTE, 1);
-//                }
-//                else if(expirationInterval<2880){//Check every hour if interval is 2 days or less
-//                    nextExecutionTime.add(Calendar.HOUR, 1);
-//                }
-//                else{//Check every day
-//                    nextExecutionTime.add(Calendar.DAY_OF_MONTH, 1);
-//                }
-//                return nextExecutionTime.getTime();
-//            }
-//        });
-//    }
 
     @Bean
     public TriggerTask rebuildSessionXmls() throws SiteConfigurationException {
@@ -80,17 +39,14 @@ public class SchedulerConfig implements SchedulingConfigurer {
 
     @Bean(destroyMethod = "shutdown")
     public ThreadPoolTaskScheduler taskScheduler() {
-        return new ThreadPoolTaskScheduler();
+        final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
+        scheduler.setRemoveOnCancelPolicy(true);
+        return scheduler;
     }
 
     @Override
     public void configureTasks(final ScheduledTaskRegistrar taskRegistrar) {
         taskRegistrar.setScheduler(taskScheduler());
-//        taskRegistrar.addTriggerTask(resetFailedLogins());
-//        taskRegistrar.addTriggerTask(disableInactiveUsers());
-//        taskRegistrar.addTriggerTask(resetEmailRequests());
-//        taskRegistrar.addTriggerTask(clearExpiredAliasTokens());
-//        taskRegistrar.addTriggerTask(rebuildSessionXmls());
         _eventService.triggerEvent(new PreferenceEvent("aliasTokenTimeout", String.valueOf(XDAT.getSiteConfigPreferences().getAliasTokenTimeout())));
         _eventService.triggerEvent(new PreferenceEvent("inactivityBeforeLockout", String.valueOf(XDAT.getSiteConfigPreferences().getInactivityBeforeLockout())));
         _eventService.triggerEvent(new PreferenceEvent("maxFailedLoginsLockoutDuration", String.valueOf(XDAT.getSiteConfigPreferences().getMaxFailedLoginsLockoutDuration())));
@@ -106,10 +62,6 @@ public class SchedulerConfig implements SchedulingConfigurer {
     @Inject
     private EmailRequestLogService _emailRequestLogService;
 
-    @Autowired
-    @Lazy
-    private JdbcTemplate _template;
-
     @Inject
     private XnatUserProvider _provider;
 
diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/AliasTokenPreferenceHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/AliasTokenPreferenceHandlerMethod.java
index 6e42ebce..67f60280 100644
--- a/src/main/java/org/nrg/xnat/event/listeners/methods/AliasTokenPreferenceHandlerMethod.java
+++ b/src/main/java/org/nrg/xnat/event/listeners/methods/AliasTokenPreferenceHandlerMethod.java
@@ -32,22 +32,18 @@ public class AliasTokenPreferenceHandlerMethod extends AbstractSiteConfigPrefere
 
     @Override
     public void handlePreference(final String preference, final String value) {
-        if(PREFERENCES.contains(preference)){
+        if (PREFERENCES.contains(preference)) {
             updateAliasTokenTimeout();
         }
     }
 
-    private void updateAliasTokenTimeout(){
+    private void updateAliasTokenTimeout() {
         try {
-            _scheduler.getScheduledThreadPoolExecutor().setRemoveOnCancelPolicy(true);
-            Iterator<Runnable> iter = _scheduler.getScheduledThreadPoolExecutor().getQueue().iterator();
-
-            for(ScheduledFuture temp: scheduledAliasTokenTimeouts){
-                temp.cancel(false);
+            for (final ScheduledFuture future : _timeouts) {
+                future.cancel(false);
             }
-
-            scheduledAliasTokenTimeouts.add(_scheduler.schedule(new ClearExpiredAliasTokens(_template), new CronTrigger(XDAT.getSiteConfigPreferences().getAliasTokenTimeoutSchedule())));
-
+            _timeouts.clear();
+            _timeouts.add(_scheduler.schedule(new ClearExpiredAliasTokens(_template), new CronTrigger(XDAT.getSiteConfigPreferences().getAliasTokenTimeoutSchedule())));
         } catch (Exception e1) {
             _log.error("", e1);
         }
@@ -60,7 +56,7 @@ public class AliasTokenPreferenceHandlerMethod extends AbstractSiteConfigPrefere
     @Lazy
     private JdbcTemplate _template;
 
-    private              ArrayList<ScheduledFuture> scheduledAliasTokenTimeouts = new ArrayList<>();
+    private ArrayList<ScheduledFuture> _timeouts = new ArrayList<>();
 
     @Autowired
     @Qualifier("taskScheduler")
-- 
GitLab