>From 0d58d0a003eb4b5c34d2ca4b7820a1737439d05d Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Thu, 29 May 2014 15:31:11 -0700
Subject: [PATCH] TPS Token Profile Resolver Plugin Framework - Ticket#447
 Mapping tokens to tokentype

---
 .../authentication/UidPwdDirAuthentication.java    |   2 +
 base/tps-tomcat/shared/conf/CS.cfg.in              | 174 ++++++-----
 base/tps-tomcat/shared/conf/registry.cfg           |   5 +
 .../src/org/dogtagpki/server/tps/TPSSubsystem.java |   8 +
 .../org/dogtagpki/server/tps/engine/TPSEngine.java |   2 +
 .../server/tps/processor/TPSProcessor.java         | 348 +++++----------------
 .../tps/profile/BaseTokenProfileResolver.java      |  38 +++
 .../tps/profile/MappingTokenProfileResolver.java   | 295 +++++++++++++++++
 .../server/tps/profile/TokenProfileParams.java     | 144 +++++++++
 .../tps/profile/TokenProfileResolverManager.java   | 114 +++++++
 10 files changed, 777 insertions(+), 353 deletions(-)
 create mode 100644 base/tps-tomcat/shared/conf/registry.cfg
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/profile/BaseTokenProfileResolver.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/profile/MappingTokenProfileResolver.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/profile/TokenProfileParams.java
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/profile/TokenProfileResolverManager.java

diff --git a/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java
index 85fe19635d48cdde6987247bab9fbc4935658c25..c85644d59eb4ab0354517140c623f3e36eb5d93c 100644
--- a/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java
+++ b/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java
@@ -59,6 +59,7 @@ public class UidPwdDirAuthentication extends DirBasedAuthentication
     public static final String CRED_UID = "uid";
     public static final String CRED_PWD = "pwd";
     protected static String[] mRequiredCreds = { CRED_UID, CRED_PWD };
+    public static final String USERID = "userid";
 
     /* Holds configuration parameters accepted by this implementation.
      * This list is passed to the configuration console so configuration
@@ -151,6 +152,7 @@ public class UidPwdDirAuthentication extends DirBasedAuthentication
             conn.authenticate(userdn, pwd);
             // set uid in the token.
             token.set(CRED_UID, uid);
+            token.set(USERID, uid);
 
             return userdn;
         } catch (ELdapException e) {
diff --git a/base/tps-tomcat/shared/conf/CS.cfg.in b/base/tps-tomcat/shared/conf/CS.cfg.in
index 28bfbb81b5108f642bf85567078276a5b83c8fee..90e90a456744122b559904798ec1fba1335e9987 100644
--- a/base/tps-tomcat/shared/conf/CS.cfg.in
+++ b/base/tps-tomcat/shared/conf/CS.cfg.in
@@ -253,28 +253,7 @@ op.enroll._032=# Token ATR:
 op.enroll._033=#   Web Store  - 3B759400006202020201
 op.enroll._034=#########################################
 op.enroll.allowUnknownToken=true
-op.enroll.mapping.0.filter.appletMajorVersion=1
-op.enroll.mapping.0.filter.appletMinorVersion=
-op.enroll.mapping.0.filter.tokenATR=
-op.enroll.mapping.0.filter.tokenCUID.end=
-op.enroll.mapping.0.filter.tokenCUID.start=
-op.enroll.mapping.0.filter.tokenType=userKey
-op.enroll.mapping.0.target.tokenType=userKey
-op.enroll.mapping.1.filter.appletMajorVersion=
-op.enroll.mapping.1.filter.appletMinorVersion=
-op.enroll.mapping.1.filter.tokenATR=
-op.enroll.mapping.1.filter.tokenCUID.end=
-op.enroll.mapping.1.filter.tokenCUID.start=
-op.enroll.mapping.1.filter.tokenType=soKey
-op.enroll.mapping.1.target.tokenType=soKey
-op.enroll.mapping.2.filter.appletMajorVersion=
-op.enroll.mapping.2.filter.appletMinorVersion=
-op.enroll.mapping.2.filter.tokenATR=
-op.enroll.mapping.2.filter.tokenCUID.end=
-op.enroll.mapping.2.filter.tokenCUID.start=
-op.enroll.mapping.2.filter.tokenType=
-op.enroll.mapping.2.target.tokenType=userKey
-op.enroll.mapping.order=0,1,2
+op.enroll.tokenProfileResolver=enrollMappingResolver
 op.enroll.soKey.auth.enable=true
 op.enroll.soKey.auth.id=ldap2
 op.enroll.soKey.cardmgr_instance=A0000000030000
@@ -856,6 +835,7 @@ op.enroll.userKey.update.applet.requiredVersion=1.4.4d40a449
 op.enroll.userKey.update.symmetricKeys.enable=false
 op.enroll.userKey.update.symmetricKeys.requiredVersion=1
 op.format.allowUnknownToken=true
+op.format.tokenProfileResolver=formatMappingResolver
 op.format.cleanToken.auth.enable=false
 op.format.cleanToken.auth.id=ldap1
 op.format.cleanToken.ca.conn=ca1
@@ -871,55 +851,6 @@ op.format.cleanToken.update.applet.encryption=true
 op.format.cleanToken.update.applet.requiredVersion=1.4.4d40a449
 op.format.cleanToken.update.symmetricKeys.enable=false
 op.format.cleanToken.update.symmetricKeys.requiredVersion=1
-op.format.mapping.0.filter.appletMajorVersion=
-op.format.mapping.0.filter.appletMinorVersion=
-op.format.mapping.0.filter.tokenATR=
-op.format.mapping.0.filter.tokenCUID.end=
-op.format.mapping.0.filter.tokenCUID.start=
-op.format.mapping.0.filter.tokenType=soCleanUserToken
-op.format.mapping.0.target.tokenType=soCleanUserToken
-op.format.mapping.1.filter.appletMajorVersion=
-op.format.mapping.1.filter.appletMinorVersion=
-op.format.mapping.1.filter.tokenATR=
-op.format.mapping.1.filter.tokenCUID.end=
-op.format.mapping.1.filter.tokenCUID.start=
-op.format.mapping.1.filter.tokenType=soUserKey
-op.format.mapping.1.target.tokenType=soUserKey
-op.format.mapping.2.filter.appletMajorVersion=
-op.format.mapping.2.filter.appletMinorVersion=
-op.format.mapping.2.filter.tokenATR=
-op.format.mapping.2.filter.tokenCUID.end=
-op.format.mapping.2.filter.tokenCUID.start=
-op.format.mapping.2.filter.tokenType=soKey
-op.format.mapping.2.target.tokenType=soKey
-op.format.mapping.3.filter.appletMajorVersion=
-op.format.mapping.3.filter.appletMinorVersion=
-op.format.mapping.3.filter.tokenATR=
-op.format.mapping.3.filter.tokenCUID.end=
-op.format.mapping.3.filter.tokenCUID.start=
-op.format.mapping.3.filter.tokenType=userKey
-op.format.mapping.3.target.tokenType=userKey
-op.format.mapping.4.filter.appletMajorVersion=
-op.format.mapping.4.filter.appletMinorVersion=
-op.format.mapping.4.filter.tokenATR=
-op.format.mapping.4.filter.tokenCUID.end=
-op.format.mapping.4.filter.tokenCUID.start=
-op.format.mapping.4.filter.tokenType=soCleanSOToken
-op.format.mapping.4.target.tokenType=soCleanSOToken
-op.format.mapping.5.filter.appletMajorVersion=
-op.format.mapping.5.filter.appletMinorVersion=
-op.format.mapping.5.filter.tokenATR=
-op.format.mapping.5.filter.tokenCUID.end=
-op.format.mapping.5.filter.tokenCUID.start=
-op.format.mapping.5.filter.tokenType=cleanToken
-op.format.mapping.5.target.tokenType=cleanToken
-op.format.mapping.6.filter.appletMajorVersion=
-op.format.mapping.6.filter.appletMinorVersion=
-op.format.mapping.6.filter.tokenATR=
-op.format.mapping.6.filter.tokenCUID.end=
-op.format.mapping.6.filter.tokenCUID.start=
-op.format.mapping.6.target.tokenType=tokenKey
-op.format.mapping.order=0,1,2,3,4,5,6
 op.format.soCleanSOToken.auth.enable=false
 op.format.soCleanSOToken.auth.id=ldap1
 op.format.soCleanSOToken.ca.conn=ca1
@@ -1010,14 +941,7 @@ op.format.userKey.update.applet.encryption=true
 op.format.userKey.update.applet.requiredVersion=1.4.4d40a449
 op.format.userKey.update.symmetricKeys.enable=false
 op.format.userKey.update.symmetricKeys.requiredVersion=1
-op.pinReset.mapping.0.filter.appletMajorVersion=
-op.pinReset.mapping.0.filter.appletMinorVersion=
-op.pinReset.mapping.0.filter.tokenATR=
-op.pinReset.mapping.0.filter.tokenCUID.end=
-op.pinReset.mapping.0.filter.tokenCUID.start=
-op.pinReset.mapping.0.filter.tokenType=
-op.pinReset.mapping.0.target.tokenType=userKey
-op.pinReset.mapping.order=0
+op.pinReset.tokenProfileResolver=pinResetMappingResolver
 op.pinReset.userKey.auth.enable=true
 op.pinReset.userKey.auth.id=ldap1
 op.pinReset.userKey.cardmgr_instance=A0000000030000
@@ -1123,7 +1047,89 @@ preop.system.name=TPS
 preop.wizard.name=TPS Setup Wizard
 proxy.securePort=[PKI_PROXY_SECURE_PORT]
 proxy.unsecurePort=[PKI_PROXY_UNSECURE_PORT]
-registry.file=[PKI_INSTANCE_PATH]/conf/registry.cfg
+tokenProfileResolver.list=formatMappingResolver,enrollMappingResolver,pinResetMappingResolver
+tokenProfileResolver.enrollMappingResolver.class_id=mappingTokenProfileResolverImpl
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.appletMajorVersion=1
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.appletMinorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.tokenATR=
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.tokenCUID.end=
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.tokenCUID.start=
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.tokenType=userKey
+tokenProfileResolver.enrollMappingResolver.mapping.0.target.tokenType=userKey
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.appletMajorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.appletMinorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.tokenATR=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.tokenCUID.end=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.tokenCUID.start=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.tokenType=soKey
+tokenProfileResolver.enrollMappingResolver.mapping.1.target.tokenType=soKey
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.appletMajorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.appletMinorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.tokenATR=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.tokenCUID.end=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.tokenCUID.start=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.tokenType=
+tokenProfileResolver.enrollMappingResolver.mapping.2.target.tokenType=userKey
+tokenProfileResolver.enrollMappingResolver.mapping.order=0,1,2
+tokenProfileResolver.formatMappingResolver.class_id=mappingTokenProfileResolverImpl
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.tokenType=soCleanUserToken
+tokenProfileResolver.formatMappingResolver.mapping.0.target.tokenType=soCleanUserToken
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.tokenType=soUserKey
+tokenProfileResolver.formatMappingResolver.mapping.1.target.tokenType=soUserKey
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.tokenType=soKey
+tokenProfileResolver.formatMappingResolver.mapping.2.target.tokenType=soKey
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.tokenType=userKey
+tokenProfileResolver.formatMappingResolver.mapping.3.target.tokenType=userKeytokenProfileResolver.formatMappingResolver.mapping.4.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.tokenType=soCleanSOToken
+tokenProfileResolver.formatMappingResolver.mapping.4.target.tokenType=soCleanSOToken
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.tokenType=cleanToken
+tokenProfileResolver.formatMappingResolver.mapping.5.target.tokenType=cleanToken
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.6.target.tokenType=tokenKey
+tokenProfileResolver.formatMappingResolver.mapping.order=0,1,2,3,4,5,6
+tokenProfileResolver.pinResetMappingResolver.class_id=mappingTokenProfileResolverImpl
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.appletMajorVersion=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.appletMinorVersion=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.tokenATR=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.tokenCUID.end=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.tokenCUID.start=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.tokenType=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.target.tokenType=userKey
+tokenProfileResolver.pinResetMappingResolver.mapping.order=0
+registry.file=[PKI_INSTANCE_PATH]/conf/tps/registry.cfg
 selftests._000=##
 selftests._001=## Self Tests
 selftests._002=##
@@ -1193,10 +1199,10 @@ target.Authentication_Sources.pattern=auths\.instance\.$name\..*
 target.configure.list=Profiles,Subsystem_Connections,Profile_Mappings,Authentication_Sources
 target.Generals.displayname=General
 target.Generals.pattern=^applet\..*\|^general\..*\|^failover.pod.enable\|^channel\..*
-target.Profile_Mappings.displayname=Profile Mapping
-target.Profile_Mappings.list=enroll,format,pinReset
-target.Profile_Mappings.pattern=op\.$name\.mapping\..*
-target.Profiles.displayname=Profile
+target.Profile_Mappings.displayname=Token Profile Mapping Resolvers
+target.Profile_Mappings.list=enrollProfileResolver,formatProfileResolver,pinResetProfileResolver
+target.Profile_Mappings.pattern=tokenProfileResolver\.$name\.mapping\..*
+target.Profiles.displayname=Token Profile
 target.Profiles.list=userKey,soKey,soCleanUserToken,soUserKey,cleanToken,soCleanSoToken,tokenKey
 target.Profiles.pattern=op\..*\.$name\..*
 target.Subsystem_Connections.displayname=Subsystem Connection
diff --git a/base/tps-tomcat/shared/conf/registry.cfg b/base/tps-tomcat/shared/conf/registry.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..dc26ae8616e8a8406910f7b95c04149c9eac8be1
--- /dev/null
+++ b/base/tps-tomcat/shared/conf/registry.cfg
@@ -0,0 +1,5 @@
+types=tpsTokenProfileResolver
+tpsTokenProfileResolver.ids=mappingTokenProfileResolverImpl
+tpsTokenProfileResolver.mappingTokenProfileResolverImpl.class=org.dogtagpki.server.tps.profile.MappingTokenProfileResolver
+tpsTokenProfileResolver.mappingTokenProfileResolverImpl.desc=Mapping-based Token profile resolver
+tpsTokenProfileResolver.mappingTokenProfileResolverImpl.name=Mapping-based Token profile resolver
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java
index 81aabe94020737bf4a559341778d231e3921e975..cc67c60c964b966ba555ef2b1c33c736fdd4a6cb 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java
@@ -19,6 +19,7 @@ package org.dogtagpki.server.tps;
 
 import org.dogtagpki.server.tps.authentication.AuthenticationManager;
 import org.dogtagpki.server.tps.cms.ConnectionManager;
+import org.dogtagpki.server.tps.profile.TokenProfileResolverManager;
 import org.dogtagpki.server.tps.config.AuthenticatorDatabase;
 import org.dogtagpki.server.tps.config.ConfigDatabase;
 import org.dogtagpki.server.tps.config.ConnectorDatabase;
@@ -68,6 +69,7 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
     public TokenDatabase tokenDatabase;
     public ConnectionManager connManager;
     public AuthenticationManager authManager;
+    public TokenProfileResolverManager profileResolverManager;
     public TPSEngine engine;
 
     @Override
@@ -113,6 +115,8 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
         connManager.initConnectors();
         authManager = new AuthenticationManager();
         authManager.initAuthInstances();
+        profileResolverManager = new TokenProfileResolverManager();
+        profileResolverManager.initProfileResolverInstances();
         CMS.debug("TPSSubsystem: startup() ends.");
     }
 
@@ -197,6 +201,10 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
         return authManager;
     }
 
+    public TokenProfileResolverManager getProfileResolverManager() {
+        return profileResolverManager;
+    }
+
     public org.mozilla.jss.crypto.X509Certificate getSubsystemCert() throws EBaseException, NotInitializedException,
             ObjectNotFoundException, TokenException {
         IConfigStore cs = CMS.getConfigStore();
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
index b4a8aee2115270d643096576457455c9e279115f..71239a4b9b61538523673345533ca5d60971d1b2 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
@@ -107,6 +107,8 @@ public class TPSEngine {
     /* misc values */
 
     public static final String OP_FORMAT_PREFIX = "op.format";
+    public static final String CFG_PROFILE_RESOLVER = "tokenProfileResolver";
+    public static final String CFG_DEF_FORMAT_PROFILE_RESOLVER = "formatMappingResolver";
 
     public void init() {
         //ToDo
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index ede210c57b09861b9ccb0e723656bc0539fae210..4efb2fb5249a169049b3efe8eb22db3c488247b7 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -35,6 +35,8 @@ import org.dogtagpki.server.tps.cms.TKSComputeRandomDataResponse;
 import org.dogtagpki.server.tps.cms.TKSComputeSessionKeyResponse;
 import org.dogtagpki.server.tps.cms.TKSRemoteRequestHandler;
 import org.dogtagpki.server.tps.engine.TPSEngine;
+import org.dogtagpki.server.tps.profile.BaseTokenProfileResolver;
+import org.dogtagpki.server.tps.profile.TokenProfileParams;
 import org.dogtagpki.tps.apdu.APDU;
 import org.dogtagpki.tps.apdu.APDUResponse;
 import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel;
@@ -89,6 +91,7 @@ public class TPSProcessor {
     private String selectedTokenType;
 
     private String currentTokenOperation;
+    private String userid;
 
     private BeginOp beginMsg;
 
@@ -610,8 +613,10 @@ public class TPSProcessor {
      * @param prefix "op.enroll", "op.format", or "op.pinReset"
      * @param tokenType the profile name
      * @param userCred IAuthCredentials obtained from a successful requestUserId call
+     * @return IAuthToken information relating to the performed authentication
+     *                    -- plugin-specific
      */
-    public void authenticateUser(
+    public IAuthToken authenticateUser(
             String op,
             TPSAuthenticator userAuth,
             IAuthCredentials userCred)
@@ -629,9 +634,10 @@ public class TPSProcessor {
         try {
             // Authenticate user
             IAuthToken aToken = auth.authenticate(userCred);
-            if (aToken != null)
+            if (aToken != null) {
                 CMS.debug("TPSProcessor.authenticateUser: authentication success");
-            else {
+                return aToken;
+            } else {
                 CMS.debug("TPSProcessor.authenticateUser: authentication failure with aToken null");
                 throw new TPSException("TPS error user authentication failed.",
                         TPSStatus.STATUS_ERROR_LOGIN);
@@ -656,9 +662,9 @@ public class TPSProcessor {
             throws IOException, TPSException, EBaseException {
         CMS.debug("TPSProcessor.requestUserId");
         if (op.isEmpty() ||
-                cuid.isEmpty() || auth == null || extensions == null) {
-            CMS.debug("TPSProcessor.requestUserId: missing parameter(s): op, cuid, auth, or extensions");
-            throw new EBaseException("TPSProcessor.requestUserId: missing parameter(s): op, cuid, auth, or extensions");
+                cuid.isEmpty() || auth == null) {
+            CMS.debug("TPSProcessor.requestUserId: missing parameter(s): op, cuid, or auth");
+            throw new EBaseException("TPSProcessor.requestUserId: missing parameter(s): op, cuid, or auth");
         }
 
         IAuthCredentials login;
@@ -818,6 +824,7 @@ public class TPSProcessor {
 
         String External_Reg_Cfg = TPSEngine.CFG_EXTERNAL_REG + "." + "enable";
         boolean isExternalReg = false;
+        String resolverInstName = "";
 
         setCurrentTokenOperation("format");
 
@@ -830,10 +837,12 @@ public class TPSProcessor {
             CMS.debug("In TPS_Processor.Format. CardManagerAID: " + CardManagerAID + " NetKeyAID: " + NetKeyAID);
             this.isExternalReg = configStore.getBoolean(External_Reg_Cfg, false);
             CMS.debug("In TPSProcessor.format isExternalReg: " + isExternalReg);
+            resolverInstName = configStore.getString(TPSEngine.OP_FORMAT_PREFIX+
+                "."+ TPSEngine.CFG_PROFILE_RESOLVER, TPSEngine.CFG_DEF_FORMAT_PROFILE_RESOLVER);
         } catch (EBaseException e1) {
             CMS.debug("TPS_Processor.Format: Internal Error obtaining mandatory config values. Error: " + e1);
             throw new TPSException("TPS error getting config values from config store.",
-                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+                    TPSStatus.STATUS_ERROR_MISCONFIGURATION);
         }
 
         TPSBuffer aidBuf = new TPSBuffer(CardManagerAID);
@@ -882,18 +891,24 @@ public class TPSProcessor {
         CMS.debug("TPSProcessor.format: major_version " + major_version + " minor_version: " + minor_version
                 + " app_major_version: " + app_major_version + " app_minor_version: " + app_minor_version);
 
-        String tokenType;
-        IAuthCredentials userCred;
+        String tokenType = "tokenType";
+        IAuthCredentials userCred=
+                new com.netscape.certsrv.authentication.AuthCredentials();
         if (isExternalReg) {
             //ToDo, do some external Reg stuff along with authentication
             tokenType = "externalRegAddToToken";
         } else {
             CMS.debug("In TPSProcessor.format isExternalReg: OFF");
-            tokenType = getTokenType(TPSEngine.OP_FORMAT_PREFIX, major_version, minor_version, cuid, msn,
-                    beginMsg.getExtensions());
-
-            CMS.debug("TPSProcessor.format: calculated tokenType: " + tokenType);
-
+            /*
+             * Note: op.format.tokenProfileResolver=none indicates no resolver
+             *    plugin used (tokenType resolved perhaps via authentication)
+             */
+            if (!resolverInstName.equals("none") && (selectedTokenType == null)) {
+                tokenType = resolveTokenProfile(resolverInstName, cuid, msn, major_version, minor_version);
+                CMS.debug("TPSProcessor.format: calculated tokenType: " + tokenType);
+            } else {
+                CMS.debug("TPSProcessor.format: : selectedTokenType already set: " + selectedTokenType);
+            }
         }
 
         // isExternalReg : user already authenticated earlier
@@ -914,7 +929,9 @@ public class TPSProcessor {
                     TPSAuthenticator userAuth =
                             getAuthentication(TPSEngine.OP_FORMAT_PREFIX, tokenType);
                     userCred = requestUserId("format", cuid, userAuth, beginMsg.getExtensions());
-                    authenticateUser("format", userAuth, userCred);
+                    IAuthToken authToken = authenticateUser("format", userAuth, userCred);
+                    userid = authToken.getInString("userid");
+                    CMS.debug("TPSProcessor.format:: auth token userid="+ userid);
                 } catch (Exception e) {
                     // all exceptions are considered login failure
                     CMS.debug("TPSProcessor.format:: authentication exception thrown: " + e);
@@ -997,6 +1014,53 @@ public class TPSProcessor {
 
     }
 
+    /**
+     * @param resolverInstName
+     * @param cuid
+     * @param msn
+     * @param major_version
+     * @param minor_version
+     * @return
+     */
+    protected String resolveTokenProfile(
+            String resolverInstName,
+            String cuid,
+            String msn,
+            byte major_version,
+            byte minor_version)
+            throws TPSException {
+        String tokenType;
+        try {
+            TokenProfileParams pParams = new TokenProfileParams();
+            CMS.debug("In TPSProcessor.resolveTokenProfile : after new TokenProfileParams");
+            pParams.set(TokenProfileParams.PROFILE_PARAM_MAJOR_VERSION,
+                    String.valueOf((int)major_version));
+            pParams.set(TokenProfileParams.PROFILE_PARAM_MINOR_VERSION,
+                    String.valueOf((int)minor_version));
+            pParams.set(TokenProfileParams.PROFILE_PARAM_CUID, cuid);
+            pParams.set(TokenProfileParams.PROFILE_PARAM_MSN, msn);
+            if (beginMsg.getExtensions() != null) {
+                pParams.set(TokenProfileParams.PROFILE_PARAM_EXT_TOKEN_TYPE,
+                        beginMsg.getExtensions().get("tokenType"));
+                pParams.set(TokenProfileParams.PROFILE_PARAM_EXT_TOKEN_ATR,
+                        beginMsg.getExtensions().get("tokenATR"));
+            }
+            CMS.debug("In TPSProcessor.resolveTokenProfile : after setting TokenProfileParams");
+            TPSSubsystem subsystem =
+                (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+            BaseTokenProfileResolver resolverInst =
+                subsystem.getProfileResolverManager().getResolverInstance(resolverInstName);
+            tokenType = resolverInst.getTokenType(pParams);
+            CMS.debug("In TPSProcessor.resolveTokenProfile : profile resolver result: "+ tokenType);
+            setSelectedTokenType(tokenType);
+        } catch (EBaseException et) {
+            CMS.debug("In TPSProcessor.resolveTokenProfile exception:"+et);
+            throw new TPSException("TPSProcessor.resolveTokenProfile failed.",
+                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+        }
+        return tokenType;
+    }
+
     protected String getIssuerInfoValue() throws TPSException {
         IConfigStore configStore = CMS.getConfigStore();
         String info = null;
@@ -1375,260 +1439,6 @@ public class TPSProcessor {
 
     }
 
-    /* Return calculated token profile type.
-    *
-    */
-    public String getTokenType(String prefix, int major_version, int minor_version, String cuid, String msn,
-            Map<String, String> extensions) throws TPSException {
-        String tokenType = null;
-        String mappingOrder = null;
-
-        if (selectedTokenType != null) {
-            CMS.debug("TPSProcessor.getTokenType: Calling this more than once. This is not needed!");
-            return selectedTokenType;
-        }
-
-        IConfigStore configStore = CMS.getConfigStore();
-
-        String configName = prefix + "." + TPSEngine.CFG_PROFILE_MAPPING_ORDER;
-
-        try {
-            mappingOrder = configStore.getString(configName);
-        } catch (EPropertyNotFound e) {
-            throw new TPSException(
-                    "TPSProcessor.getTokenType: Token Type configuration incorrect! Mising mapping order!",
-                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-
-        } catch (EBaseException e1) {
-            //The whole feature won't work if this is wrong.
-            throw new TPSException(
-                    "TPSProcessor.getTokenType: Internal error obtaining config value.!",
-                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-        }
-
-        String targetTokenType = null;
-
-        for (String mappingId : mappingOrder.split(",")) {
-
-            CMS.debug("TPS_Processor::GetTokenType:  mapping: " + mappingId);
-
-            String mappingConfigName = prefix + ".mapping." + mappingId + ".target.tokenType";
-
-            CMS.debug("TPS_Processor::GetTokenType:  mappingConfigName: " + mappingConfigName);
-
-            //We need this to exist.
-            try {
-                targetTokenType = configStore.getString(mappingConfigName);
-            } catch (EPropertyNotFound e) {
-                throw new TPSException(
-                        "TPSProcessor.getTokenType: Token Type configuration incorrect! No target token type config value found! Config: "
-                                + mappingConfigName,
-                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-
-            } catch (EBaseException e) {
-                throw new TPSException(
-                        "TPSProcessor.getTokenType: Internal error obtaining config value. Config: "
-                                + mappingConfigName,
-                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-            }
-
-            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenType";
-
-            CMS.debug("TPS_Processor::GetTokenType:  mappingConfigName: " + mappingConfigName);
-
-            //For this and remaining cases, it is not automatically an error if we don't get anything back
-            // from the config.
-            try {
-                tokenType = configStore.getString(mappingConfigName, null);
-            } catch (EBaseException e) {
-                throw new TPSException(
-                        "TPSProcessor.getTokenType: Internal error obtaining config value. Config: "
-                                + mappingConfigName,
-                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-
-            }
-
-            CMS.debug("TPS_Processor::GetTokenType:  targetTokenType: " + targetTokenType);
-
-            if (tokenType != null && tokenType.length() > 0) {
-
-                if (extensions == null) {
-                    continue;
-                }
-
-                String eTokenType = extensions.get("tokenType");
-                if (eTokenType == null) {
-                    continue;
-                }
-
-                if (!eTokenType.equals(tokenType)) {
-                    continue;
-                }
-            }
-
-            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenATR";
-
-            CMS.debug("TPS_Processor::GetTokenType:  mappingConfigName: " + mappingConfigName);
-
-            String tokenATR = null;
-
-            try {
-                tokenATR = configStore.getString(mappingConfigName, null);
-            } catch (EBaseException e) {
-                throw new TPSException(
-                        "TPSProcessor.getTokenType: Internal error obtaining config value. Config: "
-                                + mappingConfigName,
-                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-            }
-
-            CMS.debug("TPS_Processor::GetTokenType:  tokenATR: " + tokenATR);
-
-            if (tokenATR != null && tokenATR.length() > 0) {
-                if (extensions == null) {
-                    continue;
-                }
-
-                String eTokenATR = extensions.get("tokenATR");
-
-                if (eTokenATR == null) {
-                    continue;
-                }
-
-                if (!eTokenATR.equals(tokenATR)) {
-                    continue;
-                }
-
-            }
-
-            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenCUID.start";
-
-            CMS.debug("TPS_Processor::GetTokenType:  mappingConfigName: " + mappingConfigName);
-
-            String tokenCUIDStart = null;
-
-            try {
-                tokenCUIDStart = configStore.getString(mappingConfigName, null);
-
-            } catch (EBaseException e) {
-                throw new TPSException(
-                        "TPSProcessor.getTokenType: Internal error obtaining config value. Config: "
-                                + mappingConfigName,
-                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-            }
-
-            CMS.debug("TPS_Processor::GetTokenType:  tokenCUIDStart: " + tokenCUIDStart);
-
-            if (tokenCUIDStart != null && tokenCUIDStart.length() > 0) {
-                if (cuid == null) {
-                    continue;
-                }
-
-                if (tokenCUIDStart.length() != 20) {
-                    continue;
-                }
-
-                if (cuid.compareTo(tokenCUIDStart) < 0) {
-                    continue;
-                }
-
-            }
-
-            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenCUID.end";
-
-            CMS.debug("TPS_Processor::GetTokenType:  mappingConfigName: " + mappingConfigName);
-
-            String tokenCUIDEnd = null;
-            try {
-                tokenCUIDEnd = configStore.getString(mappingConfigName, null);
-            } catch (EBaseException e) {
-                throw new TPSException(
-                        "TPSProcessor.getTokenType: Internal error obtaining config value. Config: "
-                                + mappingConfigName,
-                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-            }
-
-            CMS.debug("TPS_Processor::GetTokenType:  tokenCUIDEnd: " + tokenCUIDEnd);
-
-            if (tokenCUIDEnd != null && tokenCUIDEnd.length() > 0) {
-                if (cuid == null) {
-                    continue;
-                }
-
-                if (tokenCUIDEnd.length() != 20) {
-                    continue;
-                }
-
-                if (cuid.compareTo(tokenCUIDEnd) > 0) {
-                    continue;
-                }
-
-            }
-
-            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.appletMajorVersion";
-
-            CMS.debug("TPS_Processor::GetTokenType:  mappingConfigName: " + mappingConfigName);
-
-            String majorVersion = null;
-            String minorVersion = null;
-
-            try {
-                majorVersion = configStore.getString(mappingConfigName, null);
-            } catch (EBaseException e) {
-                throw new TPSException(
-                        "TPSProcessor.getTokenType: Internal error obtaining config value. Config: "
-                                + mappingConfigName,
-                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-            }
-
-            CMS.debug("TPS_Processor::GetTokenType:  majorVersion: " + majorVersion);
-            if (majorVersion != null && majorVersion.length() > 0) {
-
-                int major = Integer.parseInt(majorVersion);
-
-                if (major != major_version) {
-                    continue;
-                }
-            }
-
-            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.appletMinorVersion";
-
-            CMS.debug("TPS_Processor::GetTokenType:  mappingConfigName: " + mappingConfigName);
-
-            try {
-                minorVersion = configStore.getString(mappingConfigName, null);
-            } catch (EBaseException e) {
-                throw new TPSException(
-                        "TPSProcessor.getTokenType: Internal error obtaining config value. Config: "
-                                + mappingConfigName,
-                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-            }
-            CMS.debug("TPS_Processor::GetTokenType:  minorVersion " + minorVersion);
-
-            if (minorVersion != null && minorVersion.length() > 0) {
-
-                int minor = Integer.parseInt(minorVersion);
-
-                if (minor != minor_version) {
-                    continue;
-                }
-            }
-
-            //if we make it this far, we have a token type
-            CMS.debug("TPS_Processor::GetTokenType: Selected Token type: " + targetTokenType);
-            break;
-        }
-
-        if (targetTokenType == null) {
-            CMS.debug("TPSProcessor.getTokenType: end found: " + targetTokenType);
-            throw new TPSException("TPSProcessor.getTokenType: Can't find token type!",
-                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
-        }
-
-        //Set this once, it won't change for this session.
-        setSelectedTokenType(targetTokenType);
-        return targetTokenType;
-
-    }
 
     public TPSEngine getTPSEngine() {
         TPSSubsystem subsystem =
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/BaseTokenProfileResolver.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/BaseTokenProfileResolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..c62d1ed2b0bb1cc5372ceadde9b49950a940ebae
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/BaseTokenProfileResolver.java
@@ -0,0 +1,38 @@
+package org.dogtagpki.server.tps.profile;
+
+import org.dogtagpki.tps.main.TPSException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+
+/**
+ * This class implements the base TPS Profile Resolver instance
+ *
+ * @author cfu
+ */
+public abstract class BaseTokenProfileResolver {
+    protected IConfigStore configStore = null;
+    protected String instanceName = "";
+    protected String prefix = "";
+
+    public BaseTokenProfileResolver() {
+    }
+
+    public void init(String instName) {
+        instanceName = instName;
+        prefix = TokenProfileResolverManager.TOKEN_PROFILE_RESOLVER_CFG +
+                "." + instanceName;
+        configStore = CMS.getConfigStore();
+    }
+
+    public String getName() {
+        return instanceName;
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public abstract String getTokenType(TokenProfileParams pPram)
+            throws TPSException;
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/MappingTokenProfileResolver.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/MappingTokenProfileResolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..91542b8f6f47855feb32548d12ea3d23a2ecebd5
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/MappingTokenProfileResolver.java
@@ -0,0 +1,295 @@
+package org.dogtagpki.server.tps.profile;
+
+import java.lang.Integer;
+import org.dogtagpki.server.tps.engine.TPSEngine;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.msg.EndOp.TPSStatus;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+
+/**
+ * MappingTokenProfileResolver is a profile resolver plugin that calculates
+ * token type by sorting through a list of filters in mapping
+ */
+public class MappingTokenProfileResolver extends BaseTokenProfileResolver {
+
+    public MappingTokenProfileResolver() {
+    }
+
+    public String getTokenType(TokenProfileParams pParam)
+            throws TPSException {
+
+        String tokenType = null;
+        String mappingOrder = null;
+        int major_version = 0;
+        int minor_version = 0;
+        String cuid = null;
+        // String msn = null;
+        String eTokenType = null;
+        String eTokenATR = null;
+
+        CMS.debug("MappingTokenProfileResolver.getTokenType: starts");
+
+        major_version = pParam.getInt(TokenProfileParams.PROFILE_PARAM_MAJOR_VERSION);
+        CMS.debug("MappingTokenProfileResolver: param major_version =" + major_version);
+
+        minor_version = pParam.getInt(TokenProfileParams.PROFILE_PARAM_MINOR_VERSION);
+        CMS.debug("MappingTokenProfileResolver: param minor_version =" + minor_version);
+
+        cuid =  pParam.getString(TokenProfileParams.PROFILE_PARAM_CUID);
+        // msn = (String) pParam.get(TokenProfileParams.PROFILE_PARAM_MSN);
+        // they don't necessarily have extension
+        try {
+            eTokenType = pParam.getString(TokenProfileParams.PROFILE_PARAM_EXT_TOKEN_TYPE);
+            eTokenATR =  pParam.getString(TokenProfileParams.PROFILE_PARAM_EXT_TOKEN_ATR);
+        } catch (TPSException e) {
+            CMS.debug("MappingTokenProfileResolver: OK to not have extension. Continue.");
+        }
+
+        CMS.debug("MappingTokenProfileResolver: params retrieved.");
+
+        String configName = prefix + "." + TPSEngine.CFG_PROFILE_MAPPING_ORDER;
+
+        try {
+            CMS.debug("MappingTokenProfileResolver: getting mapping order:" +
+                    configName);
+            mappingOrder = configStore.getString(configName);
+        } catch (EPropertyNotFound e) {
+            CMS.debug("MappingTokenProfileResolver: exception:" + e);
+            throw new TPSException(
+                    "MappingTokenProfileResolver.getTokenType: Token Type configuration incorrect! Mising mapping order!",
+                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+
+        } catch (EBaseException e1) {
+            //The whole feature won't work if this is wrong.
+            CMS.debug("MappingTokenProfileResolver: exception:" + e1);
+            throw new TPSException(
+                    "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value.!",
+                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+        }
+
+        String targetTokenType = null;
+
+        for (String mappingId : mappingOrder.split(",")) {
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  mapping: " + mappingId);
+
+            String mappingConfigName = prefix + ".mapping." + mappingId + ".target.tokenType";
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  mappingConfigName: " + mappingConfigName);
+
+            //We need this to exist.
+            try {
+                targetTokenType = configStore.getString(mappingConfigName);
+            } catch (EPropertyNotFound e) {
+                throw new TPSException(
+                        "MappingTokenProfileResolver.getTokenType: Token Type configuration incorrect! No target token type config value found! Config: "
+                                + mappingConfigName,
+                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+
+            } catch (EBaseException e) {
+                throw new TPSException(
+                        "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+                                + mappingConfigName,
+                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+            }
+
+            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenType";
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  mappingConfigName: " + mappingConfigName);
+
+            //For this and remaining cases, it is not automatically an error if we don't get anything back
+            // from the config.
+            try {
+                tokenType = configStore.getString(mappingConfigName, null);
+            } catch (EBaseException e) {
+                throw new TPSException(
+                        "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+                                + mappingConfigName,
+                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+
+            }
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  targetTokenType: " + targetTokenType);
+
+            if (tokenType != null && tokenType.length() > 0) {
+
+                if (eTokenType == null) {
+                    continue;
+                }
+
+                //String eTokenType = extensions.get("tokenType");
+                //if (eTokenType == null) {
+                //    continue;
+                //}
+
+                if (!eTokenType.equals(tokenType)) {
+                    continue;
+                }
+            }
+
+            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenATR";
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  mappingConfigName: " + mappingConfigName);
+
+            String tokenATR = null;
+
+            try {
+                tokenATR = configStore.getString(mappingConfigName, null);
+            } catch (EBaseException e) {
+                throw new TPSException(
+                        "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+                                + mappingConfigName,
+                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+            }
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  tokenATR: " + tokenATR);
+
+            if (tokenATR != null && tokenATR.length() > 0) {
+                if (eTokenATR == null) {
+                    continue;
+                }
+
+                //String eTokenATR = extensions.get("tokenATR");
+
+                //if (eTokenATR == null) {
+                //    continue;
+                //}
+
+                if (!eTokenATR.equals(tokenATR)) {
+                    continue;
+                }
+
+            }
+
+            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenCUID.start";
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  mappingConfigName: " + mappingConfigName);
+
+            String tokenCUIDStart = null;
+
+            try {
+                tokenCUIDStart = configStore.getString(mappingConfigName, null);
+
+            } catch (EBaseException e) {
+                throw new TPSException(
+                        "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+                                + mappingConfigName,
+                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+            }
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  tokenCUIDStart: " + tokenCUIDStart);
+
+            if (tokenCUIDStart != null && tokenCUIDStart.length() > 0) {
+                if (cuid == null) {
+                    continue;
+                }
+
+                if (tokenCUIDStart.length() != 20) {
+                    continue;
+                }
+
+                if (cuid.compareTo(tokenCUIDStart) < 0) {
+                    continue;
+                }
+
+            }
+
+            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenCUID.end";
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  mappingConfigName: " + mappingConfigName);
+
+            String tokenCUIDEnd = null;
+            try {
+                tokenCUIDEnd = configStore.getString(mappingConfigName, null);
+            } catch (EBaseException e) {
+                throw new TPSException(
+                        "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+                                + mappingConfigName,
+                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+            }
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  tokenCUIDEnd: " + tokenCUIDEnd);
+
+            if (tokenCUIDEnd != null && tokenCUIDEnd.length() > 0) {
+                if (cuid == null) {
+                    continue;
+                }
+
+                if (tokenCUIDEnd.length() != 20) {
+                    continue;
+                }
+
+                if (cuid.compareTo(tokenCUIDEnd) > 0) {
+                    continue;
+                }
+
+            }
+
+            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.appletMajorVersion";
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  mappingConfigName: " + mappingConfigName);
+
+            String majorVersion = null;
+            String minorVersion = null;
+
+            try {
+                majorVersion = configStore.getString(mappingConfigName, null);
+            } catch (EBaseException e) {
+                throw new TPSException(
+                        "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+                                + mappingConfigName,
+                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+            }
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  majorVersion: " + majorVersion);
+            if (majorVersion != null && majorVersion.length() > 0) {
+
+                int major = Integer.parseInt(majorVersion);
+
+                if (major != major_version) {
+                    continue;
+                }
+            }
+
+            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.appletMinorVersion";
+
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  mappingConfigName: " + mappingConfigName);
+
+            try {
+                minorVersion = configStore.getString(mappingConfigName, null);
+            } catch (EBaseException e) {
+                throw new TPSException(
+                        "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+                                + mappingConfigName,
+                        TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+            }
+            CMS.debug("MappingTokenProfileResolver.getTokenType:  minorVersion " + minorVersion);
+
+            if (minorVersion != null && minorVersion.length() > 0) {
+
+                int minor = Integer.parseInt(minorVersion);
+
+                if (minor != minor_version) {
+                    continue;
+                }
+            }
+
+            //if we make it this far, we have a token type
+            CMS.debug("MappingTokenProfileResolver.getTokenType: Selected Token type: " + targetTokenType);
+            break;
+        }
+
+        if (targetTokenType == null) {
+            CMS.debug("MappingTokenProfileResolver.getTokenType: end found: " + targetTokenType);
+            throw new TPSException("MappingTokenProfileResolver.getTokenType: Can't find token type!",
+                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+        }
+
+        return targetTokenType;
+
+    }
+
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/TokenProfileParams.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/TokenProfileParams.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4789373eb9583674936118ef0897ddea7670d75
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/TokenProfileParams.java
@@ -0,0 +1,144 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.profile;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.netscape.certsrv.apps.CMS;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.msg.EndOp.TPSStatus;
+
+/**
+ * A class represents profile params information.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class TokenProfileParams {
+
+    public static final String PROFILE_PARAM_MAJOR_VERSION = "pp_major_version";
+    public static final String PROFILE_PARAM_MINOR_VERSION = "pp_minor_version";
+    public static final String PROFILE_PARAM_CUID = "pp_cuid";
+    public static final String PROFILE_PARAM_MSN = "pp_msn";
+    public static final String PROFILE_PARAM_EXT_TOKEN_TYPE = "pp_ext_tokenType";
+    public static final String PROFILE_PARAM_EXT_TOKEN_ATR = "pp_ext_tokenATR";
+
+    private HashMap<String, String> content = new HashMap<String, String>();
+
+    /**
+     * Constructs a meta information.
+     * <P>
+     */
+    public TokenProfileParams() {
+    }
+
+    /**
+     * Returns a short string describing this certificate attribute.
+     * <P>
+     *
+     * @return information about this certificate attribute.
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer("[\n" + "  Meta information:\n");
+
+        for (Map.Entry<String, String> entry : content.entrySet()) {
+            String key = entry.getKey();
+
+            sb.append("  " + key + " : " + entry.getValue() + "\n");
+        }
+        sb.append("]\n");
+        return sb.toString();
+    }
+
+    /**
+     * Gets a String attribute value.
+     * <P>
+     *
+     * @param name the name of the attribute to return.
+     */
+    public String getString(String name)
+           throws TPSException {
+        String val = content.get(name);
+        if (val == null) {
+            CMS.debug("TokenProfileParams.getString: param null:"+ name);
+            throw new TPSException (
+                    "TokenProfileParams.getString: param null:"+ name,
+                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+        }
+        return val;
+    }
+
+    /**
+     * Gets an int attribute value.
+     * <P>
+     *
+     * @param name the name of the attribute to return.
+     */
+    public int getInt(String name)
+           throws TPSException {
+        String val = content.get(name);
+        if (val == null) {
+            CMS.debug("TokenProfileParams.getInt: param null:"+ name);
+            throw new TPSException (
+                    "TokenProfileParams.getInt: param null:"+ name,
+                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+        }
+        try {
+            int intVal = Integer.parseInt(val);
+            return intVal;
+        } catch (NumberFormatException e) {
+            CMS.debug("TokenProfileParams.getInt: param "+ name + "=" + val + e);
+            throw new TPSException (
+                    "TokenProfileParams.getInt: param major_version:"+ e,
+                    TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+        }
+    }
+
+    /**
+     * Sets an attribute value.
+     *
+     * @param name the name of the attribute
+     * @param val the attribute value.
+     */
+    public void set(String name, String val) {
+        content.put(name, val);
+    }
+
+    /**
+     * Deletes an attribute value from this AttrSet.
+     * <P>
+     *
+     * @param name the name of the attribute to delete.
+     */
+    public void delete(String name) {
+        content.remove(name);
+    }
+
+    /**
+     * Returns an enumeration of the names of the attributes existing within
+     * this attribute.
+     * <P>
+     *
+     * @return an enumeration of the attribute names.
+     */
+    public Set<String> getElements() {
+        return content.keySet();
+    }
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/TokenProfileResolverManager.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/TokenProfileResolverManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6325fccaf79525d701a0fb2a44f48767bd1e30e
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/profile/TokenProfileResolverManager.java
@@ -0,0 +1,114 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.profile;
+
+import java.util.HashMap;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
+
+/**
+ * TokenProfileResolverManager is a class for profile resolver plugin
+ * management
+ *
+ * @author cfu
+ */
+public class TokenProfileResolverManager
+{
+    private static final String TOKEN_PROFILE_RESOLVER_TYPE = "tpsTokenProfileResolver";
+    public static final String PROP_RESOLVER_LIST = "list";
+    public static final String PROP_RESOLVER_CLASS_ID = "class_id";
+
+    protected static final String TOKEN_PROFILE_RESOLVER_CFG = "tokenProfileResolver";
+    protected IPluginRegistry registry = null;
+    protected HashMap<String, BaseTokenProfileResolver> tokenProfileResolvers = null;
+
+    public TokenProfileResolverManager() {
+        tokenProfileResolvers = new HashMap<String, BaseTokenProfileResolver>();
+    }
+
+    /**
+     * initializes all profile resolver plugin instances specified in
+     * <instance-name>/conf/registry.cfg
+     *
+     * configuration e.g.
+     *
+     * registry.cfg:
+     * types=tpsTokenProfileResolver
+     * tpsProfileResolver.ids=mappingTokenProfileResolverImpl
+     * tpsProfileResolver.mappingTokenProfileResolverImpl.class=org.dogtagpki.server.tps.profile.MappingTokenProfileResolver
+     * tpsProfileResolver.mappingTokenProfileResolverImpl.desc=Mapping-based Token profile resolver
+     * tpsProfileResolver.mappingTokenProfileResolverImpl.name=Mapping-based Token profile resolver
+     *
+     * CS.cfg :
+     * registry.file=/var/lib/pki/pki-tomcat/conf/tps/registry.cfg
+     * tokenProfileResolver.list=formatMappingResolver,enrollMappingResolver,pinResetMappingResolver
+     * tokenProfileResolver.formatMappingResolver.class_id=mappingProfileResolverImpl
+     * tokenProfileResolver.formatMappingResolver.[plugin-specific configuration]
+     *
+     * op.format.tokenProfileResolver=formatMappingResolver
+     * ...
+     * op.enroll.tokenProfileResolver=enrollMappingResolver
+     *
+     * Note: "none" indicates no resolver plugin applied
+     * op.format.tokenProfileResolver=none
+     */
+    public void initProfileResolverInstances()
+            throws EBaseException {
+
+        CMS.debug("TokenProfileResolverManager: initProfileResolverInstances(): begins");
+        IConfigStore conf = CMS.getConfigStore();
+        registry = (IPluginRegistry) CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY);
+        if (registry == null) {
+            CMS.debug("TokenProfileResolverManager: initProfileResolverInstances(): registry null");
+            return;
+        }
+
+        IConfigStore prConf = conf.getSubStore(TOKEN_PROFILE_RESOLVER_CFG);
+        String profileList = prConf.getString(PROP_RESOLVER_LIST, "");
+
+        for (String prInst : profileList.split(",")) {
+            String classID = prConf.getString(prInst + "." + PROP_RESOLVER_CLASS_ID);
+            CMS.debug("TokenProfileResolverManager: initProfileResolverInstances(): initializing classID=" + classID);
+            IPluginInfo resolverInfo =
+                    registry.getPluginInfo(TOKEN_PROFILE_RESOLVER_TYPE, classID);
+            String resolverClass = resolverInfo.getClassName();
+            BaseTokenProfileResolver resolver = null;
+            try {
+                resolver = (BaseTokenProfileResolver)
+                        Class.forName(resolverClass).newInstance();
+            } catch (Exception e) {
+                // throw Exception
+                CMS.debug("TokenProfileResolverManager: resolver plugin Class.forName " +
+                        resolverClass + " " + e.toString());
+                throw new EBaseException(e.toString());
+            }
+            resolver.init(prInst);
+            tokenProfileResolvers.put(prInst, resolver);
+            CMS.debug("TokenProfileResolverManager: initProfileResolverInstances(): resolver instance added: " + prInst);
+        }
+    }
+
+    public BaseTokenProfileResolver getResolverInstance(String name) {
+        return tokenProfileResolvers.get(name);
+    }
+}
-- 
1.8.4.2

