From a4d179661754e04c882c1686e3c83f1b458717df Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 11 Apr 2019 16:52:19 +0200 Subject: refactoring of AuthData builder --- .../builder/AbstractAuthenticationDataBuilder.java | 331 ++++++++++++++++----- 1 file changed, 257 insertions(+), 74 deletions(-) (limited to 'eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java') diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java index f578afd8..2482d65f 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java @@ -36,6 +36,8 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; import org.springframework.util.Base64Utils; import org.w3c.dom.DOMException; import org.w3c.dom.Element; @@ -43,18 +45,23 @@ import org.w3c.dom.Node; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.ExtendedPVPAttributeDefinitions; import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; import at.gv.egiz.eaaf.core.api.idp.IAuthenticationDataBuilder; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; import at.gv.egiz.eaaf.core.api.idp.auth.data.IAuthProcessDataContainer; import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; +import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; import at.gv.egiz.eaaf.core.exceptions.EAAFBuilderException; import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; import at.gv.egiz.eaaf.core.exceptions.EAAFParserException; import at.gv.egiz.eaaf.core.exceptions.XPathException; import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser; import at.gv.egiz.eaaf.core.impl.utils.XPathUtils; @@ -67,7 +74,221 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati protected Collection includedToGenericAuthData = null; @Autowired protected IConfiguration basicConfig; - protected void generateBasicAuthData(AuthenticationData authData, IRequest pendingReq, + @Override + public IAuthData buildAuthenticationData(IRequest pendingReq) throws EAAFAuthenticationException { + IAuthData authData = null; + final IAuthProcessDataContainer authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class); + + try { + if (authProcessData.isEIDProcess()) { + log.debug("Building AuthData from new E-ID information ... "); + authData = getAuthDataInstance(pendingReq); + Assert.notNull(authData, "AuthData is null"); + + log.trace("Adding generic AuthData information ... "); + buildInternalAuthDataGeneric(authData, authProcessData, pendingReq); + + log.trace("Build service-specific AuthData information ... "); + buildServiceSpecificAuthenticationData(authData, pendingReq); + + } else { + log.info("User authentication uses the deprecated. Building AuthData from deprecated information ... "); + authData = buildDeprecatedAuthData(pendingReq); + Assert.notNull(authData, "AuthData is null"); + + } + + + } catch (XPathException | DOMException | EAAFException e) { + log.warn("Can not build authentication data from auth. process information"); + throw new EAAFAuthenticationException("builder.11", new Object[]{e.getMessage()}, e); + + } + + log.trace("AuthData generation finished"); + return authData; + + } + + /** + * * @param pendingReq current pendingRequest + * + * @param pendingReq current pendingRequest + * @return {@link IAuthData} but never null + * @throws EAAFException + */ + @NonNull + abstract protected IAuthData getAuthDataInstance(IRequest pendingReq) throws EAAFException; + + /** + * Build service-specific AuthData by using information from E-ID + * This builder uses vSZ, MDS and Consent as input information + * + * @param pendingReq current pendingRequest + * @return {@link IAuthData} but never null + * @throws EAAFException + */ + abstract protected void buildServiceSpecificAuthenticationData(IAuthData authData, IRequest pendingReq) throws EAAFException; + + + /** + * Add generic E-ID information into already existing AuthData + * + * @param authData + * @param authProcessData + * @param pendingReq + */ + private void buildInternalAuthDataGeneric(@NonNull IAuthData authData, + @NonNull IAuthProcessDataContainer authProcessData, @NonNull IRequest pendingReq) { + Assert.notNull(pendingReq, "PendingRequest is null"); + Assert.notNull(authData, "AuthData is null"); + Assert.notNull(authProcessData, "AuthProcessData is null"); + + if (!(authData instanceof AuthenticationData)) { + log.error("AuthData has no suitable type! Requires: {}", AuthenticationData.class.getName()); + throw new RuntimeException("AuthData has no suitable type! Requires: " + AuthenticationData.class.getName()); + + } + + final AuthenticationData internalAuthData = (AuthenticationData)authData; + + //TODO: check if it is needed +// if (authProcessData.getGenericSessionDataStorage() != null && +// !authProcessData.getGenericSessionDataStorage().isEmpty()) +// includedToGenericAuthData = authProcessData.getGenericSessionDataStorage().keySet(); +// else + includedToGenericAuthData = new ArrayList(); + + //#################################################### + //set general authData info's + internalAuthData.setAuthenticationIssuer(pendingReq.getAuthURL()); + internalAuthData.setSsoSession(pendingReq.needSingleSignOnFunctionality()); + internalAuthData.setBaseIDTransferRestrication(pendingReq.getServiceProviderConfiguration().hasBaseIdTransferRestriction()); + + //#################################################### + //set MDS and vSZ + internalAuthData.setFamilyName(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.PRINCIPAL_NAME_NAME, String.class)); + internalAuthData.setGivenName(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.GIVEN_NAME_NAME, String.class)); + internalAuthData.setDateOfBirth(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.BIRTHDATE_NAME, String.class)); + internalAuthData.setEncSourceId(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.EID_ENCRYPTED_SOURCEID_NAME, String.class)); + internalAuthData.setEncSourceIdType(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.EID_ENCRYPTED_SOURCEID_TYPE_NAME, String.class)); + + + //#################################################### + //set QAA level + setQAALevel(internalAuthData, authProcessData, pendingReq); + + + //#################################################### + //set isForeigner flag + setFlagForeigner(internalAuthData, authProcessData, pendingReq); + + + //#################################################### + //set citizen country-code + setCitizenCountryCode(internalAuthData, authProcessData, pendingReq); + + } + + /** + * Parse citzen country-code into AuthData + * + * @param internalAuthData + * @param authProcessData + * @param pendingReq + */ + private void setCitizenCountryCode(AuthenticationData authData, IAuthProcessDataContainer authProcessData, + IRequest pendingReq) { + includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_ISSUING_NATION_NAME); + final String pvpCCCAttr = authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class); + if (StringUtils.isNotEmpty(pvpCCCAttr)) { + authData.setCiticenCountryCode(pvpCCCAttr); + log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_ISSUING_NATION_FRIENDLY_NAME); + + } else { + if (authData.isForeigner()) { + //TODO!!!! + + } else { + authData.setCiticenCountryCode(basicConfig.getBasicConfiguration( + IConfiguration.CONFIG_PROPS_AUTH_DEFAULT_COUNTRYCODE, + EAAFConstants.COUNTRYCODE_AUSTRIA)); + + } + } + + } + + /** + * parse QAA Level into AuthData + * + * @param authData + * @param authProcessData + * @param pendingReq + */ + private void setQAALevel(@NonNull AuthenticationData authData, + @NonNull IAuthProcessDataContainer authProcessData, @NonNull IRequest pendingReq) { + includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME); + String currentLoA = null; + if (StringUtils.isNotEmpty(authProcessData.getQAALevel())) + currentLoA = authProcessData.getQAALevel(); + else { + currentLoA = authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, String.class); + if (StringUtils.isNotEmpty(currentLoA)) { + log.debug("Find PVP-Attr '" + PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME + "':" + currentLoA + + " --> Parse QAA-Level from that attribute."); + + } + } + if (StringUtils.isNotEmpty(currentLoA)) { + if (currentLoA.startsWith(EAAFConstants.EIDAS_LOA_PREFIX)) { + authData.seteIDASLoA(currentLoA); + + } else + log.info("Only eIDAS LoAs are supported by this implementation"); + + } else { + log.info("No QAA level found. Set to default level " + EAAFConstants.EIDAS_LOA_LOW); + authData.seteIDASLoA(EAAFConstants.EIDAS_LOA_LOW); + + } + + } + + /** + * Parse Foreigner information into AuthData + * + * @param authData + * @param authProcessData + * @param pendingReq + */ + private void setFlagForeigner(AuthenticationData authData, IAuthProcessDataContainer authProcessData, IRequest pendingReq) { + //TODO: change to new eIDAS-token attribute identifier + if (authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_STORK_TOKEN_NAME) != null) { + log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_STORK_TOKEN_FRIENDLY_NAME + + " --> Set 'isForeigner' flag to TRUE"); + authData.setForeigner(true); + + } else { + authData.setForeigner(authProcessData.isForeigner()); + + } + } + + /** + * Build authentication data by using information from citizen-card or mobile-phone signature + * This builder uses IdentityLink, AuthBlock, full MIS mandate as input information + * + * @param pendingReq current pendingRequest + * @return {@link IAuthData} but never null + * @throws EAAFException + */ + @Deprecated + @NonNull + abstract protected IAuthData buildDeprecatedAuthData(IRequest pendingReq) throws EAAFException; + + @Deprecated + protected void generateDeprecatedBasicAuthData(AuthenticationData authData, IRequest pendingReq, IAuthProcessDataContainer authProcessData) throws EAAFBuilderException, EAAFConfigurationException, XPathException, DOMException, EAAFParserException { if (authProcessData.getGenericSessionDataStorage() != null && @@ -86,13 +307,13 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati //#################################################### //parse user info's from identityLink IIdentityLink idlFromPVPAttr = null; - IIdentityLink identityLink = authProcessData.getIdentityLink(); + final IIdentityLink identityLink = authProcessData.getIdentityLink(); if (identityLink != null) { parseBasicUserInfosFromIDL(authData, identityLink, includedToGenericAuthData); } else { // identityLink is not direct in MOASession - String pvpAttrIDL = authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_IDENTITY_LINK_NAME, String.class); + final String pvpAttrIDL = authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_IDENTITY_LINK_NAME, String.class); //find PVP-Attr. which contains the IdentityLink if (StringUtils.isNotEmpty(pvpAttrIDL)) { log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_IDENTITY_LINK_FRIENDLY_NAME @@ -106,10 +327,10 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati //set identitylink into AuthProcessData authProcessData.setIdentityLink(idlFromPVPAttr);; - } catch (EAAFParserException e) { + } catch (final EAAFParserException e) { log.warn("Received IdentityLink is not valid", e); - } catch (Exception e) { + } catch (final Exception e) { log.warn("Received IdentityLink is not valid", e); } finally { @@ -118,7 +339,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati if (idlStream != null) idlStream.close(); - } catch (IOException e) { + } catch (final IOException e) { log.warn("Close InputStream FAILED.", e); } @@ -154,72 +375,27 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati authData.setIdentificationType(null); } + //#################################################### //set QAA level - includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME); - String currentLoA = null; - if (StringUtils.isNotEmpty(authProcessData.getQAALevel())) - currentLoA = authProcessData.getQAALevel(); - else { - currentLoA = authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, String.class); - if (StringUtils.isNotEmpty(currentLoA)) { - log.debug("Find PVP-Attr '" + PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME + "':" + currentLoA - + " --> Parse QAA-Level from that attribute."); - - } - } - if (StringUtils.isNotEmpty(currentLoA)) { - if (currentLoA.startsWith(EAAFConstants.EIDAS_LOA_PREFIX)) { - authData.seteIDASLoA(currentLoA); - - } else - log.info("Only eIDAS LoAs are supported by this implementation"); - - } else { - log.info("No QAA level found. Set to default level " + EAAFConstants.EIDAS_LOA_LOW); - authData.seteIDASLoA(EAAFConstants.EIDAS_LOA_LOW); + setQAALevel(authData, authProcessData, pendingReq); - } //#################################################### - //set isForeigner flag - //TODO: change to new eIDAS-token attribute identifier - if (authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_STORK_TOKEN_NAME) != null) { - log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_STORK_TOKEN_FRIENDLY_NAME - + " --> Set 'isForeigner' flag to TRUE"); - authData.setForeigner(true); - - } else { - authData.setForeigner(authProcessData.isForeigner()); - - } + //set isForeigner flag + setFlagForeigner(authData, authProcessData, pendingReq); + //#################################################### //set citizen country-code - includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_ISSUING_NATION_NAME); - String pvpCCCAttr = authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class); - if (StringUtils.isNotEmpty(pvpCCCAttr)) { - authData.setCiticenCountryCode(pvpCCCAttr); - log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_ISSUING_NATION_FRIENDLY_NAME); - - } else { - if (authData.isForeigner()) { - //TODO!!!! - - } else { - authData.setCiticenCountryCode(basicConfig.getBasicConfiguration( - IConfiguration.CONFIG_PROPS_AUTH_DEFAULT_COUNTRYCODE, - EAAFConstants.COUNTRYCODE_AUSTRIA)); - - } - } + setCitizenCountryCode(authData, authProcessData, pendingReq); //#################################################### // set bPK and IdentityLink - String pvpbPKValue = getbPKValueFromPVPAttribute(authProcessData); - String pvpbPKTypeAttr = getbPKTypeFromPVPAttribute(authProcessData); - Pair pvpEncbPKAttr = getEncryptedbPKFromPVPAttribute(authProcessData, authData, pendingReq.getServiceProviderConfiguration()); + final String pvpbPKValue = getbPKValueFromPVPAttribute(authProcessData); + final String pvpbPKTypeAttr = getbPKTypeFromPVPAttribute(authProcessData); + final Pair pvpEncbPKAttr = getEncryptedbPKFromPVPAttribute(authProcessData, authData, pendingReq.getServiceProviderConfiguration()); //check if a unique ID for this citizen exists if (StringUtils.isEmpty(authData.getIdentificationValue()) && @@ -250,7 +426,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati // baseID is in AuthSesson --> calculate bPK directly } else if (StringUtils.isNotEmpty(authData.getIdentificationValue())) { log.debug("Citizen baseID is in MOASession --> calculate bPK from this."); - Pair result = buildOAspecificbPK(pendingReq, authData); + final Pair result = buildOAspecificbPK(pendingReq, authData); authData.setBPK(result.getFirst()); authData.setBPKType(result.getSecond()); @@ -276,12 +452,12 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati } } - Pair baseIDFromSZR = getbaseIDFromSZR(authData, notValidbPK, notValidbPKType); + final Pair baseIDFromSZR = getbaseIDFromSZR(authData, notValidbPK, notValidbPKType); if (baseIDFromSZR != null) { log.info("Receive citizen baseID from SRZ. Authentication can be completed"); authData.setIdentificationValue(baseIDFromSZR.getFirst()); authData.setIdentificationType(baseIDFromSZR.getSecond()); - Pair result = buildOAspecificbPK(pendingReq, authData); + final Pair result = buildOAspecificbPK(pendingReq, authData); authData.setBPK(result.getFirst()); authData.setBPKType(result.getSecond()); @@ -310,24 +486,26 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati } //extract a encrypted bPK from PVP attrobute + @Deprecated protected abstract Pair getEncryptedbPKFromPVPAttribute(IAuthProcessDataContainer authProcessDataContainer, AuthenticationData authData, ISPConfiguration spConfig) throws EAAFBuilderException; //request baseId from SRZ + @Deprecated protected abstract Pair getbaseIDFromSZR(AuthenticationData authData, String notValidbPK, String notValidbPKType); - + @Deprecated protected Pair buildOAspecificbPK(IRequest pendingReq, AuthenticationData authData) throws EAAFBuilderException { - ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); + final ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); - String baseID = authData.getIdentificationValue(); - String baseIDType = authData.getIdentificationType(); + final String baseID = authData.getIdentificationValue(); + final String baseIDType = authData.getIdentificationType(); Pair sectorSpecId = null; if (EAAFConstants.URN_PREFIX_BASEID.equals(baseIDType)) { //SAML1 legacy target parameter work-around - String spTargetId = oaParam.getAreaSpecificTargetIdentifier(); + final String spTargetId = oaParam.getAreaSpecificTargetIdentifier(); log.debug("Use OA target identifier '" + spTargetId + "' from configuration"); //calculate sector specific unique identifier @@ -344,18 +522,19 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati } + @Deprecated protected IIdentityLink buildOAspecificIdentityLink(ISPConfiguration spConfig, IIdentityLink idl, String bPK, String bPKType) throws EAAFConfigurationException, XPathException, DOMException, EAAFParserException { if (spConfig.hasBaseIdTransferRestriction()) { log.debug("SP: " + spConfig.getUniqueIdentifier() + " has baseId transfer restriction. Remove baseId from IDL ..."); - Element idlassertion = idl.getSamlAssertion(); + final Element idlassertion = idl.getSamlAssertion(); //set bpk/wpbk; - Node prIdentification = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); + final Node prIdentification = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); prIdentification.getFirstChild().setNodeValue(bPK); //set bkp/wpbk type - Node prIdentificationType = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_TYPE_XPATH); + final Node prIdentificationType = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_TYPE_XPATH); prIdentificationType.getFirstChild().setNodeValue(bPKType); - SimpleIdentityLinkAssertionParser idlparser = new SimpleIdentityLinkAssertionParser(idlassertion); + final SimpleIdentityLinkAssertionParser idlparser = new SimpleIdentityLinkAssertionParser(idlassertion); return idlparser.parseIdentityLink(); } else @@ -371,6 +550,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati * @param bPKType bPK-Type to check * @return true, if bPK-Type matchs to Service-Provider configuration, otherwise false */ + @Deprecated private boolean matchsReceivedbPKToOnlineApplication(ISPConfiguration oaParam, String bPKType) { return oaParam.getAreaSpecificTargetIdentifier().equals(bPKType); @@ -383,6 +563,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati * @param identityLink * @param includedGenericSessionData */ + @Deprecated private void parseBasicUserInfosFromIDL(AuthenticationData authData, IIdentityLink identityLink, Collection includedGenericSessionData) { authData.setIdentificationValue(identityLink.getIdentificationValue()); authData.setIdentificationType(identityLink.getIdentificationType()); @@ -422,6 +603,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati * @param session MOASession, but never null * @return bPK, which was received by PVP-Attribute, or null if no attribute exists */ + @Deprecated private String getbPKValueFromPVPAttribute(IAuthProcessDataContainer session) { String pvpbPKValueAttr = session.getGenericDataFromSession(PVPAttributeDefinitions.BPK_NAME, String.class); if (StringUtils.isNotEmpty(pvpbPKValueAttr)) { @@ -434,7 +616,7 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati } - String[] spitted = pvpbPKValueAttr.split(":"); + final String[] spitted = pvpbPKValueAttr.split(":"); if (spitted.length == 2) { log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME); return spitted[1]; @@ -464,8 +646,9 @@ public abstract class AbstractAuthenticationDataBuilder implements IAuthenticati * @param session MOASession, but never null * @return bPKType, which was received by PVP-Attribute, or null if no attribute exists */ + @Deprecated private String getbPKTypeFromPVPAttribute(IAuthProcessDataContainer session) { - String pvpbPKTypeAttr = session.getGenericDataFromSession(PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, String.class); + final String pvpbPKTypeAttr = session.getGenericDataFromSession(PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, String.class); if (StringUtils.isNotEmpty(pvpbPKTypeAttr)) { // //fix a wrong bPK-Type encoding, which was used in some PVP Standardportal implementations -- cgit v1.2.3