diff options
Diffstat (limited to 'eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp')
86 files changed, 8863 insertions, 8906 deletions
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/AuthenticationData.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/AuthenticationData.java index a6bf247a..a6fe5ff0 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/AuthenticationData.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/AuthenticationData.java @@ -1,526 +1,525 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp; import java.io.Serializable; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; -import java.util.List; import java.util.Map; import java.util.TimeZone; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; + import org.apache.commons.collections4.map.HashedMap; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; -import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; -import at.gv.egiz.eaaf.core.impl.data.Pair; - /** + * Service-Provider specific authentication data. + * * @author tlenz * */ -public class AuthenticationData implements IAuthData, Serializable { - - private static final Logger log = LoggerFactory.getLogger(AuthenticationData.class); - - private static final long serialVersionUID = -1042697056735596866L; - public static final String IDENTITY_LINK_DATE_FORMAT = "yyyy-MM-dd"; - - private boolean isBaseIDTransferRestrication = true; - private final Map<String, Object> genericDataStorate = new HashedMap<String, Object>(); - - private String issuer; - private Date issueInstant; - - @Deprecated private String identificationValue; - @Deprecated private String identificationType; - @Deprecated private IIdentityLink identityLink = null; - - private String familyName; - private String givenName; - private Date dateOfBirth; - - private String encSourceId; - private String encSourceIdType; - - - - @Deprecated private String bPK; - @Deprecated private String bPKType; - @Deprecated private List<Pair<String, String>> additionalBpks; - - private String ccc = null; - - - private boolean foreigner =false; - private String eIDASLoA = null; - - private boolean ssoSession = false; - private Date ssoSessionValidTo = null; - - private String sessionIndex = null; - private String nameID = null; - private String nameIDFormat = null; - - public AuthenticationData() { - this.issueInstant = new Date(); - - } - - @Override - public String getAuthenticationIssuer() { - return this.issuer; - } - - /** - * Set an unique identifier for the IDP that authenticates the user - * - * @param authIssuer - */ - public void setAuthenticationIssuer(final String authIssuer) { - this.issuer = authIssuer; - - } - - - @Override - public Date getAuthenticationIssueInstant() { - return this.issueInstant; - } - - - @Override - public String getAuthenticationIssueInstantString() { - final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - f.setTimeZone(TimeZone.getTimeZone("UTC")); - return f.format(this.issueInstant); - - } - - /** - * Set the timestamp for this user authentication process - * - * @param date - */ - public void setAuthenticationIssueInstant(final Date date) { - this.issueInstant = date; - } - - @Override - public String getCiticenCountryCode() { - return this.ccc; - } - - - @Override - @Deprecated - public String getBPK() { - return bPK; - } - - /** - * Sets the bPK. - * @param bPK The bPK to set - */ - @Deprecated - public void setBPK(final String bPK) { - this.bPK = bPK; - } - - - @Override - public Date getDateOfBirth() { - return this.dateOfBirth; - } - - @Override - public String getFormatedDateOfBirth() { - final DateFormat pvpDateFormat = new SimpleDateFormat(IDENTITY_LINK_DATE_FORMAT); - if (getDateOfBirth() != null) - return pvpDateFormat.format(getDateOfBirth()); - else - return "2999-12-31"; - - } - - - @Override - public String getFamilyName() { - return this.familyName; - } - - - @Override - public String getGivenName() { - return this.givenName; - } - - @Override - public String getEncryptedSourceId() { - return this.encSourceId; - } - - @Override - public String getEncryptedSourceIdType() { - return this.encSourceIdType; - } - - @Override - @Deprecated - public String getIdentificationValue() { - return identificationValue; - } - - - @Override - @Deprecated - public String getIdentificationType() { - return identificationType; - } - - @Override - @Deprecated - public IIdentityLink getIdentityLink() { - return identityLink; - } - - /** - * @param identityLink the identityLink to set - */ - @Deprecated - public void setIdentityLink(final IIdentityLink identityLink) { - this.identityLink = identityLink; - } - - /** - * Sets the dateOfBirth. - * @param dateOfBirth The dateOfBirth to set - */ - public void setDateOfBirth(final Date dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } - - public void setDateOfBirth(final String dateOfBirth) { - try { - if (StringUtils.isNotEmpty(dateOfBirth)) { - final DateFormat identityLinkFormat = new SimpleDateFormat(IDENTITY_LINK_DATE_FORMAT); - this.dateOfBirth = identityLinkFormat.parse(dateOfBirth); - - } - - } catch (final ParseException e) { - log.warn("Parse dateOfBirht from IdentityLink FAILED", e); - - } - } - - /** - * Sets the familyName. - * @param familyName The familyName to set - */ - public void setFamilyName(final String familyName) { - this.familyName = familyName; - } - - /** - * Sets the givenName. - * @param givenName The givenName to set - */ - public void setGivenName(final String givenName) { - this.givenName = givenName; - } - - /** - * Sets the identificationValue. - * @param identificationValue The identificationValue to set - */ - @Deprecated - public void setIdentificationValue(final String identificationValue) { - this.identificationValue = identificationValue; - } - - /** - * Sets the identificationType. - * @param identificationType The identificationType to set - */ - @Deprecated - public void setIdentificationType(final String identificationType) { - this.identificationType = identificationType; - } - - - @Override - @Deprecated - public String getBPKType() { - return bPKType; - } - - /** - * Set sector identifier of user's bPK - * - * @param bPKType - */ - @Deprecated - public void setBPKType(final String bPKType) { - this.bPKType = bPKType; - } - - @Override - public String getEIDASQAALevel() { - return this.eIDASLoA; - - } - - - @Override - public boolean isForeigner() { - return this.foreigner; - } - - - /** - * Indicate the the user is a foreigner - * - * @param true if the user is a foreigner, otherwise false - */ - public void setForeigner(final boolean foreigner) { - this.foreigner = foreigner; - } - - @Override - public boolean isSsoSession() { - return ssoSession; - } - - - /** - * Indicate that the authentication was done by using an active SSO session - * - * @param true if a SSO was used, otherwise false - */ - public void setSsoSession(final boolean ssoSession) { - this.ssoSession = ssoSession; - } - - - /** - * Country Code for the authenticated user - * - * @param ccc Two letter country code - */ - public void setCiticenCountryCode(final String ccc) { - this.ccc = ccc; - } - - @Override - public String getSessionIndex() { - return sessionIndex; - } - - /** - * @param sessionIndex the sessionIndex to set - */ - public void setSessionIndex(final String sessionIndex) { - this.sessionIndex = sessionIndex; - } - - - @Override - public String getNameID() { - return this.nameID; - } - - /** - * @param nameID the nameID to set - */ - public void setNameID(final String nameID) { - this.nameID = nameID; - } - - /** - * @return the nameIDFormat - */ - @Override - public String getNameIDFormat() { - return nameIDFormat; - } - - /** - * @param nameIDFormat the nameIDFormat to set - */ - public void setNameIDFormat(final String nameIDFormat) { - this.nameIDFormat = nameIDFormat; - } - - /** - * @return the ssoSessionValidTo - */ - @Override - public Date getSsoSessionValidTo() { - return ssoSessionValidTo; - } - - /** - * @param ssoSessionValidTo the ssoSessionValidTo to set - */ - public void setSsoSessionValidTo(final Date ssoSessionValidTo) { - this.ssoSessionValidTo = ssoSessionValidTo; - } - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.data.IAuthData#isBusinessService() - */ - @Override - public boolean isBaseIDTransferRestrication() { - return isBaseIDTransferRestrication; - } - - /** - * @param isBaseIDTransmittionAllowed the isBaseIDTransmittionAllowed to set - */ - public void setBaseIDTransferRestrication(final boolean isBaseIDTransferRestrication) { - this.isBaseIDTransferRestrication = isBaseIDTransferRestrication; - } - - /** - * Returns a generic data-object with is stored with a specific identifier - * - * @param key The specific identifier of the data object - * @param clazz The class type which is stored with this key - * @return The data object or null if no data is found with this key - */ - @Override - public <T> T getGenericData(final String key, final Class<T> clazz) { - if (StringUtils.isNotEmpty(key)) { - final Object data = genericDataStorate.get(key); - - if (data == null) - return null; - - try { - @SuppressWarnings("unchecked") - final - T test = (T) data; - return test; - - } catch (final Exception e) { - log.warn("Generic authentication-data object can not be casted to requsted type", e); - return null; - - } - - } - - log.info("Can not load generic session-data with key='null'"); - return null; - - } - - /** - * Store a generic data-object to session with a specific identifier - * - * @param key Identifier for this data-object - * @param object Generic data-object which should be stored. This data-object had to be implement the 'java.io.Serializable' interface - * @throws SessionDataStorageException Error message if the data-object can not stored to generic session-data storage - */ - public void setGenericData(final String key, final Object object) throws EAAFStorageException { - if (StringUtils.isEmpty(key)) { - log.info("Generic session-data can not be stored with a 'null' key"); - throw new EAAFStorageException("Generic data can not be stored with a 'null' key", null); - - } - - if (object != null) { - if (!Serializable.class.isInstance(object)) { - log.warn("Generic data can only store objects which implements the 'Seralizable' interface"); - throw new EAAFStorageException("Generic data can only store objects which implements the 'Seralizable' interface", null); - - } - } - - if (genericDataStorate.containsKey(key)) - log.debug("Overwrite generic data with key:" + key); - else - log.trace("Add generic data with key:" + key + " to session."); - - genericDataStorate.put(key, object); - } - - public void seteIDASLoA(final String eIDASLoA) { - this.eIDASLoA = eIDASLoA; - } - - @Override - @Deprecated - public List<Pair<String, String>> getAdditionalbPKs() { - return this.additionalBpks; - } - - - /** - * Set the encrypted SourceId for current authenticated user - * - * @param encSourceId - */ - public void setEncSourceId(final String encSourceId) { - this.encSourceId = encSourceId; - } - - /** - * Set the type identifier of the encrypted SourceId - * - * @param encSourceIdType - */ - public void setEncSourceIdType(final String encSourceIdType) { - this.encSourceIdType = encSourceIdType; - } - - - - /** - * Add an additional bPK Pair<bPK, bPKType> into authdata - * - * @param bPK Pair<bPK, bPKType> - */ - @Deprecated - public void addAdditionalbPKPair(final Pair<String, String> bPK) { - if (this.additionalBpks == null) { - this.additionalBpks = new ArrayList<Pair<String, String>>(); - - } - - this.additionalBpks.add(bPK); - } +public class AuthenticationData implements IAuthData, Serializable { + + private static final Logger log = LoggerFactory.getLogger(AuthenticationData.class); + + private static final long serialVersionUID = -1042697056735596866L; + public static final String IDENTITY_LINK_DATE_FORMAT = "yyyy-MM-dd"; + + private boolean isBaseIdTransferRestrication = true; + private final Map<String, Object> genericDataStorate = new HashedMap<>(); + + private String issuer; + private Date issueInstant; + + @Deprecated + private String identificationValue; + @Deprecated + private String identificationType; + @Deprecated + private IIdentityLink identityLink = null; + + private String familyName; + private String givenName; + private Date dateOfBirth; + + private String encSourceId; + private String encSourceIdType; + + private String bpk; + private String bpkType; + + private String ccc = null; + + private boolean foreigner = false; + private String eidasLoa = null; + + private boolean ssoSession = false; + private Date ssoSessionValidTo = null; + + private String sessionIndex = null; + private String nameID = null; + private String nameIdFormat = null; + + public AuthenticationData() { + this.issueInstant = new Date(); + + } + + @Override + public String getAuthenticationIssuer() { + return this.issuer; + } + + /** + * Set an unique identifier for the IDP that authenticates the user. + * + * @param authIssuer Issuer of this authentication information + */ + public void setAuthenticationIssuer(final String authIssuer) { + this.issuer = authIssuer; + + } + + @Override + public Date getAuthenticationIssueInstant() { + return getDateCopyOrNull(this.issueInstant); + + } + + @Override + public String getAuthenticationIssueInstantString() { + final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + f.setTimeZone(TimeZone.getTimeZone("UTC")); + return f.format(this.issueInstant); + + } + + /** + * Set the timestamp for this user authentication process. + * + * @param date Authentication data + */ + public void setAuthenticationIssueInstant(final Date date) { + this.issueInstant = getDateCopyOrNull(date); + } + + @Override + public String getCiticenCountryCode() { + return this.ccc; + } + + @Override + @Deprecated + public String getBpk() { + return bpk; + } + + /** + * Sets the bPK. + * + * @param bpk The bPK to set + */ + @Deprecated + public void setBpk(final String bpk) { + this.bpk = bpk; + } + + @Override + public Date getDateOfBirth() { + return getDateCopyOrNull(this.dateOfBirth); + + } + + @Override + public String getFormatedDateOfBirth() { + final DateFormat pvpDateFormat = new SimpleDateFormat(IDENTITY_LINK_DATE_FORMAT); + if (getDateOfBirth() != null) { + return pvpDateFormat.format(getDateOfBirth()); + } else { + return "2999-12-31"; + } + + } + + @Override + public String getFamilyName() { + return this.familyName; + } + + @Override + public String getGivenName() { + return this.givenName; + } + + @Override + public String getEncryptedSourceId() { + return this.encSourceId; + } + + @Override + public String getEncryptedSourceIdType() { + return this.encSourceIdType; + } + + @Override + @Deprecated + public String getIdentificationValue() { + return identificationValue; + } + + @Override + @Deprecated + public String getIdentificationType() { + return identificationType; + } + + @Override + @Deprecated + public IIdentityLink getIdentityLink() { + return identityLink; + } + + /** + * Set the IdentityLink. + * + * @param identityLink the identityLink to set + */ + @Deprecated + public void setIdentityLink(final IIdentityLink identityLink) { + this.identityLink = identityLink; + } + + /** + * Sets the dateOfBirth. + * + * @param dateOfBirth The dateOfBirth to set + */ + public void setDateOfBirth(final Date dateOfBirth) { + this.dateOfBirth = getDateCopyOrNull(dateOfBirth); + } + + /** + * Set the date of birth. + * + * @param dateOfBirth date of birth String as "yyyy-MM-dd" + */ + public void setDateOfBirth(final String dateOfBirth) { + try { + if (StringUtils.isNotEmpty(dateOfBirth)) { + final DateFormat identityLinkFormat = new SimpleDateFormat(IDENTITY_LINK_DATE_FORMAT); + this.dateOfBirth = identityLinkFormat.parse(dateOfBirth); + + } + + } catch (final ParseException e) { + log.warn("Parse dateOfBirht from IdentityLink FAILED", e); + + } + } + + /** + * Sets the familyName. + * + * @param familyName The familyName to set + */ + public void setFamilyName(final String familyName) { + this.familyName = familyName; + } + + /** + * Sets the givenName. + * + * @param givenName The givenName to set + */ + public void setGivenName(final String givenName) { + this.givenName = givenName; + } + + /** + * Sets the identificationValue. + * + * @param identificationValue The identificationValue to set + */ + @Deprecated + public void setIdentificationValue(final String identificationValue) { + this.identificationValue = identificationValue; + } + + /** + * Sets the identificationType. + * + * @param identificationType The identificationType to set + */ + @Deprecated + public void setIdentificationType(final String identificationType) { + this.identificationType = identificationType; + } + + @Override + @Deprecated + public String getBpkType() { + return bpkType; + } + + /** + * Set sector identifier of user's bPK. + * + * @param bpkType bPK type + */ + @Deprecated + public void setBpkType(final String bpkType) { + this.bpkType = bpkType; + } + + @Override + public String getEidasQaaLevel() { + return this.eidasLoa; + + } + + @Override + public boolean isForeigner() { + return this.foreigner; + } + + /** + * Indicate the the user is a foreigner. + * + * @param foreigner true if the user is a foreigner, otherwise false + */ + public void setForeigner(final boolean foreigner) { + this.foreigner = foreigner; + } + + @Override + public boolean isSsoSession() { + return ssoSession; + } + + /** + * Indicate that the authentication was done by using an active SSO session. + * + * @param ssoSession true if a SSO was used, otherwise false + */ + public void setSsoSession(final boolean ssoSession) { + this.ssoSession = ssoSession; + } + + /** + * Country Code for the authenticated user. + * + * @param ccc Two letter country code + */ + public void setCiticenCountryCode(final String ccc) { + this.ccc = ccc; + } + + @Override + public String getSessionIndex() { + return sessionIndex; + } + + /** + * Set an index for this session. + * + * @param sessionIndex the sessionIndex to set. + */ + public void setSessionIndex(final String sessionIndex) { + this.sessionIndex = sessionIndex; + } + + @Override + public String getNameID() { + return this.nameID; + } + + /** + * Set User's nameId. + * + * @param nameID the nameID to set. + */ + public void setNameID(final String nameID) { + this.nameID = nameID; + } + + /** + * Get format of User's NameId. + * + * @return the nameIDFormat. + */ + @Override + public String getNameIdFormat() { + return nameIdFormat; + } + + /** + * Set format of User's NameId. + * + * @param nameIdFormat the nameIDFormat to set. + */ + public void setNameIdFormat(final String nameIdFormat) { + this.nameIdFormat = nameIdFormat; + } + + /** + * Get SSO session valid period. + * + * @return the ssoSessionValidTo + */ + @Override + public Date getSsoSessionValidTo() { + return getDateCopyOrNull(ssoSessionValidTo); + } + + /** + * Set SSO session valid period. + * + * @param ssoSessionValidTo the ssoSessionValidTo to set + */ + public void setSsoSessionValidTo(final Date ssoSessionValidTo) { + this.ssoSessionValidTo = getDateCopyOrNull(ssoSessionValidTo); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.data.IAuthData#isBusinessService() + */ + @Override + public boolean isBaseIdTransferRestrication() { + return isBaseIdTransferRestrication; + } + + /** + * Set baseId transfer restriction. + * + * @param isBaseIdTransferRestrication the isBaseIDTransmittionAllowed to set + */ + public void setBaseIdTransferRestrication(final boolean isBaseIdTransferRestrication) { + this.isBaseIdTransferRestrication = isBaseIdTransferRestrication; + } + + /** + * Returns a generic data-object with is stored with a specific identifier. + * + * @param key The specific identifier of the data object + * @param clazz The class type which is stored with this key + * @return The data object or null if no data is found with this key + */ + @Override + public <T> T getGenericData(final String key, final Class<T> clazz) { + if (StringUtils.isNotEmpty(key)) { + final Object data = genericDataStorate.get(key); + + if (data == null) { + return null; + } + + try { + @SuppressWarnings("unchecked") + final T test = (T) data; + return test; + + } catch (final Exception e) { + log.warn("Generic authentication-data object can not be casted to requsted type", e); + return null; + + } + + } + + log.info("Can not load generic session-data with key='null'"); + return null; + + } + + /** + * Store a generic data-object to session with a specific identifier. + * + * @param key Identifier for this data-object + * @param object Generic data-object which should be stored. This data-object + * had to be implement the 'java.io.Serializable' interface + * @throws SessionDataStorageException Error message if the data-object can not + * stored to generic session-data storage + */ + public void setGenericData(final String key, final Object object) throws EaafStorageException { + if (StringUtils.isEmpty(key)) { + log.info("Generic session-data can not be stored with a 'null' key"); + throw new EaafStorageException("Generic data can not be stored with a 'null' key", null); + + } + + if (object != null && !Serializable.class.isInstance(object)) { + log.warn( + "Generic data can only store objects which implements the 'Seralizable' interface"); + throw new EaafStorageException( + "Generic data can only store objects which implements the 'Seralizable' interface", + null); + } + + if (genericDataStorate.containsKey(key)) { + log.debug("Overwrite generic data with key:" + key); + } else { + log.trace("Add generic data with key:" + key + " to session."); + } + + genericDataStorate.put(key, object); + } + + public void setEidasLoa(final String eidasLoa) { + this.eidasLoa = eidasLoa; + } + + + + /** + * Set the encrypted SourceId for current authenticated user. + * + * @param encSourceId encryped baseId + */ + public void setEncSourceId(final String encSourceId) { + this.encSourceId = encSourceId; + } + + /** + * Set the type identifier of the encrypted SourceId. + * + * @param encSourceIdType type identifier of encryped baseId + */ + public void setEncSourceIdType(final String encSourceIdType) { + this.encSourceIdType = encSourceIdType; + } + + private Date getDateCopyOrNull(Date in) { + if (in != null) { + return new Date(in.getTime()); + } else { + return null; + } + } + } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EAAFCoreSpringResourceProvider.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EAAFCoreSpringResourceProvider.java deleted file mode 100644 index c7c8010b..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EAAFCoreSpringResourceProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -import at.gv.egiz.components.spring.api.SpringResourceProvider; - -public class EAAFCoreSpringResourceProvider implements SpringResourceProvider { - - @Override - public String getName() { - return "EAAF Core SpringResourceProvider"; - } - - @Override - public String[] getPackagesToScan() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Resource[] getResourcesToLoad() { - ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_core.beans.xml", EAAFCoreSpringResourceProvider.class); - - return new Resource[] {sl20AuthConfig}; - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EaafCoreSpringResourceProvider.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EaafCoreSpringResourceProvider.java new file mode 100644 index 00000000..3548684b --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EaafCoreSpringResourceProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +public class EaafCoreSpringResourceProvider implements SpringResourceProvider { + + @Override + public String getName() { + return "EAAF Core SpringResourceProvider"; + } + + @Override + public String[] getPackagesToScan() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Resource[] getResourcesToLoad() { + final ClassPathResource sl20AuthConfig = + new ClassPathResource("/eaaf_core.beans.xml", EaafCoreSpringResourceProvider.class); + + return new Resource[] { sl20AuthConfig }; + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EidAuthenticationData.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EidAuthenticationData.java index 86728c05..5779f12b 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EidAuthenticationData.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EidAuthenticationData.java @@ -8,114 +8,117 @@ import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; import org.springframework.util.Assert; -import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions.EID_IDENTITY_STATUS_LEVEL_VALUES; +import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions.EidIdentityStatusLevelValues; import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; public class EidAuthenticationData extends AuthenticationData implements IEidAuthData { - private static final Logger log = LoggerFactory.getLogger(EidAuthenticationData.class); - - - private static final long serialVersionUID = -7106142572904327044L; - - private byte[] eIDToken; - private byte[] signerCertificate; - private EID_IDENTITY_STATUS_LEVEL_VALUES eidStatus; - private String vdaEndpointUrl; - private boolean useMandate = false; - - @Override - public byte[] getSignerCertificate() { - return this.signerCertificate; - } - - @Override - public byte[] getEIDToken() { - return this.eIDToken; - } - - @Override - public EID_IDENTITY_STATUS_LEVEL_VALUES getEIDStatus() { - return this.eidStatus; - - } - - @Override - public boolean isUseMandate() { - return useMandate; - } - - @Override - public String getVdaEndPointUrl() { - return vdaEndpointUrl; - - } - - /** - * Set the status of the E-ID identity - * - * @param eidStatus - */ - public void setEidStatus(EID_IDENTITY_STATUS_LEVEL_VALUES eidStatus) { - this.eidStatus = eidStatus; - } - - /** - * Set Online IdentityLink to AuthenticationData - * - * @param eIDToken - */ - public void seteIDToken(final byte[] eIDToken) { - this.eIDToken = eIDToken; - - } - - /** - * Set the signing certificate that was used to sign the user consent - * - * @param signerCertificate - */ - public void setSignerCertificate(@NonNull final X509Certificate signerCertificate) { - Assert.notNull(signerCertificate, "Signer certificate is null"); - try { - this.signerCertificate = signerCertificate.getEncoded(); - - } catch (final CertificateEncodingException e) { - log.warn("Can NOT serialized signer-certificate", e); - log.warn("Signer certificate will be ignored"); - - } - } - - /** - * Set the signing certificate that was used to sign the user consent - * - * @param signerCertificate - */ - public void setSignerCertificate(final byte[] signerCertificate) { - this.signerCertificate = signerCertificate; - - } - - /** - * Set flag that mandates are used in this process - * - * @param useMandate true if mandates was used, otherwise false - */ - public void setUseMandate(boolean useMandate) { - this.useMandate = useMandate; - } - - - /** - * Set URL of the EndPoint that was used on VDA for authentication - * - * @param vdaEndpointUrl - */ - public void setVdaEndpointUrl(String vdaEndpointUrl) { - this.vdaEndpointUrl = vdaEndpointUrl; - } - - - - + private static final Logger log = LoggerFactory.getLogger(EidAuthenticationData.class); + + private static final long serialVersionUID = -7106142572904327044L; + + private byte[] eidToken; + private byte[] signerCertificate; + private EidIdentityStatusLevelValues eidStatus; + private String vdaEndpointUrl; + private boolean useMandate = false; + + @Override + public byte[] getSignerCertificate() { + return getByteCopyOrNull(this.signerCertificate); + } + + @Override + public byte[] getEidToken() { + return getByteCopyOrNull(this.eidToken); + } + + @Override + public EidIdentityStatusLevelValues getEidStatus() { + return this.eidStatus; + + } + + @Override + public boolean isUseMandate() { + return useMandate; + } + + @Override + public String getVdaEndPointUrl() { + return vdaEndpointUrl; + + } + + /** + * Set the status of the E-ID identity. + * + * @param eidStatus Status of the E-ID + */ + public void setEidStatus(final EidIdentityStatusLevelValues eidStatus) { + this.eidStatus = eidStatus; + } + + /** + * Set Online IdentityLink to AuthenticationData. + * + * @param eidToken Online-IdentityLink + */ + public void setEidToken(final byte[] eidToken) { + this.eidToken = getByteCopyOrNull(eidToken); + + } + + /** + * Set the signing certificate that was used to sign the user consent. + * + * @param signerCertificate User's signer certificate + */ + public void setSignerCertificate(@NonNull final X509Certificate signerCertificate) { + Assert.notNull(signerCertificate, "Signer certificate is null"); + try { + this.signerCertificate = signerCertificate.getEncoded(); + + } catch (final CertificateEncodingException e) { + log.warn("Can NOT serialized signer-certificate", e); + log.warn("Signer certificate will be ignored"); + + } + } + + /** + * Set the signing certificate that was used to sign the user consent. + * + * @param signerCertificate User's signer certificate + */ + public void setSignerCertificate(final byte[] signerCertificate) { + this.signerCertificate = getByteCopyOrNull(signerCertificate); + + } + + /** + * Set flag that mandates are used in this process. + * + * @param useMandate true if mandates was used, otherwise false + */ + public void setUseMandate(final boolean useMandate) { + this.useMandate = useMandate; + } + + /** + * Set URL of the EndPoint that was used on VDA for authentication. + * + * @param vdaEndpointUrl Used VDA end-point + */ + public void setVdaEndpointUrl(final String vdaEndpointUrl) { + this.vdaEndpointUrl = vdaEndpointUrl; + } + + private byte[] getByteCopyOrNull(byte[] in) { + if (in != null) { + return in.clone(); + } else { + return null; + } + } + } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java index 4cefcd8d..d2365e4a 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.auth; import java.io.IOException; @@ -44,327 +37,348 @@ import org.springframework.beans.factory.annotation.Autowired; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IRequestStorage; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; 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.ISpConfiguration; import at.gv.egiz.eaaf.core.api.idp.auth.IAuthenticationManager; -import at.gv.egiz.eaaf.core.api.idp.auth.ISSOManager; +import at.gv.egiz.eaaf.core.api.idp.auth.ISsoManager; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine; import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.exceptions.EAAFSSOException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafSsoException; import at.gv.egiz.eaaf.core.exceptions.NoPassivAuthenticationException; import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.ModuleRegistration; import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; public abstract class AbstractAuthenticationManager implements IAuthenticationManager { - private static final Logger log = LoggerFactory.getLogger(AbstractAuthenticationManager.class); - - private static List<String> reqParameterWhiteListeForModules = new ArrayList<String>(); - private static List<String> reqHeaderWhiteListeForModules = new ArrayList<String>(); - - public static final String MOA_SESSION = "MoaAuthenticationSession"; - public static final String MOA_AUTHENTICATED = "MoaAuthenticated"; - - public static final int SLOTIMEOUT = 30 * 1000; //30 sec - - @Autowired(required=true) protected IConfiguration authConfig; - @Autowired(required=true) private ProcessEngine processEngine; - @Autowired(required=true) private IRequestStorage requestStoreage; - @Autowired(required=true) protected IRevisionLogger revisionsLogger; - @Autowired(required=false) protected ISSOManager ssoManager; - - /* (non-Javadoc) - * @see at.gv.egiz.eaaf.core.impl.idp.auth.IAuthenticationManager#addParameterNameToWhiteList(java.lang.String) - */ - @Override - public final void addParameterNameToWhiteList(String httpReqParam) { - if (StringUtils.isNotEmpty(httpReqParam)) - reqParameterWhiteListeForModules.add(httpReqParam); - - } - - /* (non-Javadoc) - * @see at.gv.egiz.eaaf.core.impl.idp.auth.IAuthenticationManager#addHeaderNameToWhiteList(java.lang.String) - */ - @Override - public final void addHeaderNameToWhiteList(String httpReqParam) { - if (StringUtils.isNotEmpty(httpReqParam)) - reqHeaderWhiteListeForModules.add(httpReqParam.toLowerCase()); - - } - - /* (non-Javadoc) - * @see at.gv.egiz.eaaf.core.impl.idp.auth.IAuthenticationManager#addHeaderNameToWhiteList(java.lang.String) - */ - @Override - public final boolean doAuthentication(HttpServletRequest httpReq, HttpServletResponse httpResp, - IRequest pendingReq) throws EAAFException { - - if (!(pendingReq instanceof RequestImpl)) { - log.error("Requests that need authentication MUST be of type 'RequestImpl'"); - throw new RuntimeException("Requests that need authentication HAS TO BE of type 'RequestImpl'"); - - } - - //load OA configuration from pending request - final ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); - - //set logging context and log unique OA identifier to revision log - TransactionIDUtils.setServiceProviderId(oaParam.getUniqueIdentifier()); - revisionsLogger.logEvent(pendingReq, EVENT_AUTHENTICATION_PROCESS_FOR_SP, pendingReq.getSPEntityId()); - - //generic authentication request validation - if (pendingReq.isPassiv() && pendingReq.forceAuth()) { - // conflict! - throw new NoPassivAuthenticationException(); - } - - - //check Single Sign-On functionality if SSOManager is available - boolean isValidSSOSession = false; - if (ssoManager != null) { - log.trace("SSOManager is loaded. Starting SSO session validation ... "); - //check if SSO is allowed for this service provider - ssoManager.isSSOAllowedForSP(pendingReq, httpReq); - - //check if SSO session is active and valid - isValidSSOSession = ssoManager.checkAndValidateSSOSession(pendingReq, httpReq, httpResp) && - pendingReq.needSingleSignOnFunctionality(); - - - } - - //check if session is already authenticated - //boolean isSessionAuthenticated = tryPerformAuthentication((RequestImpl) pendingReq, isValidSSOSession); - //boolean isSessionAuthenticated = isValidSSOSession && StringUtils.isNotEmpty(pendingReq.getSSOSessionIdentifier()); - - - //force new authentication authentication process - if (pendingReq.forceAuth()) { - startAuthenticationProcess(httpReq, httpResp, (RequestImpl) pendingReq); - return false; - - //perform SSO-Consents evaluation if it it required - } else if (isValidSSOSession && pendingReq.isNeedUserConsent()) { - sendSingleSignOnConsentsEvaluation(httpReq, httpResp, (RequestImpl) pendingReq); - return false; - - - } else if (pendingReq.isPassiv()) { - if (isValidSSOSession && - StringUtils.isNotEmpty(pendingReq.getInternalSSOSessionIdentifier()) ) { - // Passive authentication ok! --> Populate pending request from SSO session - ssoManager.populatePendingRequestWithSSOInformation(pendingReq); - revisionsLogger.logEvent(pendingReq, EVENT_AUTHENTICATION_PROCESS_FINISHED); - return true; - - } else { - throw new NoPassivAuthenticationException(); - - } - - } else { - if (isValidSSOSession && - StringUtils.isNotEmpty(pendingReq.getInternalSSOSessionIdentifier())) { - // Is authenticated .. proceed - ssoManager.populatePendingRequestWithSSOInformation(pendingReq); - revisionsLogger.logEvent(pendingReq, EVENT_AUTHENTICATION_PROCESS_FINISHED); - return true; - - } else { - // Start authentication! - startAuthenticationProcess(httpReq, httpResp, (RequestImpl) pendingReq); - return false; - - } - } - } - - @Override - public final void performOnlyIDPLogOut(HttpServletRequest request, HttpServletResponse response, IRequest pendingReq) { - - log.debug("Close session. Remove pending request ... "); - requestStoreage.removePendingRequest(pendingReq.getPendingRequestId()); - - - if (ssoManager != null) { - try { - log.trace("'SSOManager' active. Search for active SSO sessions ... "); - if (ssoManager.destroySSOSessionOnIDPOnly(request, response, pendingReq)) - log.info("SSO session successfully closed"); - else - log.info("Closing SSO session NOT successfully"); - - } catch (final EAAFSSOException e) { - log.warn("Destroying of SSO session FAILED. Reason: " + e.getMessage(), e); - - } - - } - - } - - /** - * Populate process execution context and start process engine - * - * @param httpReq - * @param httpResp - * @param pendingReq - * @throws ServletException - * @throws IOException - * @throws EAAFException - */ - private void startAuthenticationProcess(HttpServletRequest httpReq, - HttpServletResponse httpResp, RequestImpl pendingReq) - throws EAAFException { - - log.info("Starting authentication ..."); - revisionsLogger.logEvent(pendingReq, EVENT_AUTHENTICATION_PROCESS_STARTED); - - //create authentication process execution context - final ExecutionContext executionContext = new ExecutionContextImpl(); - - //set oaIdentifeir - executionContext.put(EAAFConstants.PROCESS_ENGINE_SERVICE_PROVIDER_ENTITYID, - pendingReq.getServiceProviderConfiguration().getUniqueIdentifier()); - - //add X509 SSL client certificate if exist - if (httpReq.getAttribute("javax.servlet.request.X509Certificate") != null) { - log.debug("Find SSL-client-certificate on request --> Add it to context"); - executionContext.put(EAAFConstants.PROCESS_ENGINE_SSL_CLIENT_CERTIFICATE, - ((X509Certificate[])httpReq.getAttribute("javax.servlet.request.X509Certificate"))); - pendingReq.setRawDataToTransaction(EAAFConstants.PROCESS_ENGINE_SSL_CLIENT_CERTIFICATE, - (httpReq.getAttribute("javax.servlet.request.X509Certificate"))); - - } - - //add additional http request parameter to context - if (!reqParameterWhiteListeForModules.isEmpty()) { - final Enumeration<String> reqParamNames = httpReq.getParameterNames(); - while(reqParamNames.hasMoreElements()) { - final String paramName = reqParamNames.nextElement(); - if (StringUtils.isNotEmpty(paramName) && reqParameterWhiteListeForModules.contains(paramName) ) - executionContext.put(paramName, StringEscapeUtils.escapeHtml4(httpReq.getParameter(paramName))); - } - } - - //add additional http request parameter to context - if (!reqHeaderWhiteListeForModules.isEmpty()) { - final Enumeration<String> reqHeaderNames = httpReq.getHeaderNames(); - while(reqHeaderNames.hasMoreElements()) { - final String paramName = reqHeaderNames.nextElement(); - if (StringUtils.isNotEmpty(paramName) - && at.gv.egiz.eaaf.core.impl.utils.ArrayUtils.containsCaseInsensitive(paramName, reqHeaderWhiteListeForModules) - //reqHeaderWhiteListeForModules.contains(paramName.toLowerCase()) - ) - executionContext.put(paramName.toLowerCase(), StringEscapeUtils.escapeHtml4(httpReq.getHeader(paramName))); - - } - } - - - - //populate more IDP specific information to execution context - populateExecutionContext(executionContext, pendingReq, httpReq); - - //start process engine - startProcessEngine(pendingReq, executionContext); - - } - - /** - * - * - * @throws EAAFException - */ - abstract protected void populateExecutionContext(ExecutionContext executionContext, - RequestImpl pendingReq, HttpServletRequest httpReq) throws EAAFException; - - /** - * Starting a user consent evaluation - * - * @param request - * @param response - * @param pendingReq - * @throws ServletException - * @throws IOException - * @throws EAAFException - */ - private void sendSingleSignOnConsentsEvaluation(HttpServletRequest request, - HttpServletResponse response, RequestImpl pendingReq) - throws EAAFException { - - log.debug("Starting SSO user-consents evaluation ..."); - - //set authenticated flag to false, because user consents is required - pendingReq.setAuthenticated(false); - - //create execution context - final ExecutionContext executionContext = new ExecutionContextImpl(); - executionContext.put(ISSOManager.PROCESS_ENGINE_SSO_CONSENTS_EVALUATION, true); - - //start process engine - startProcessEngine(pendingReq, executionContext); - - } - - - /** - * Select a specific process and starting process engine - * - * @param pendingReq - * @param executionContext - * @throws EAAFException - */ - private void startProcessEngine(RequestImpl pendingReq, ExecutionContext executionContext) throws EAAFException { - try { - //put pending-request ID on execurtionContext - executionContext.put(EAAFConstants.PROCESS_ENGINE_PENDINGREQUESTID, pendingReq.getPendingRequestId()); - - // create process instance - final String processDefinitionId = ModuleRegistration.getInstance().selectProcess(executionContext, pendingReq); - - if (processDefinitionId == null) { - log.warn("No suitable process found for PendingReqId " + pendingReq.getPendingRequestId() ); - throw new EAAFException( - "process.02", - new Object[] {pendingReq.getPendingRequestId()}); - - } - - final String processInstanceId = processEngine.createProcessInstance(processDefinitionId, executionContext); - - // keep process instance id in protocol pending-request - pendingReq.setProcessInstanceId(processInstanceId); - - //store pending-request - requestStoreage.storePendingRequest(pendingReq); - - // start process - processEngine.start(pendingReq); - - } catch (final ProcessExecutionException e) { - final Throwable cause = e.getCause(); - if (cause != null && cause instanceof TaskExecutionException) { - final Throwable taskCause = cause.getCause(); - if (taskCause != null && taskCause instanceof EAAFException) { - final EAAFException moaTaskCause = (EAAFException) taskCause; - log.warn(taskCause.getMessage(), taskCause); - throw moaTaskCause; - - } - } - - throw new EAAFException( - "process.01", - new Object[] { pendingReq.getProcessInstanceId(), pendingReq.getPendingRequestId() }, e); - } - - } + private static final Logger log = LoggerFactory.getLogger(AbstractAuthenticationManager.class); + + private static List<String> reqParameterWhiteListeForModules = new ArrayList<>(); + private static List<String> reqHeaderWhiteListeForModules = new ArrayList<>(); + + public static final String MOA_SESSION = "MoaAuthenticationSession"; + public static final String MOA_AUTHENTICATED = "MoaAuthenticated"; + + public static final int SLOTIMEOUT = 30 * 1000; // 30 sec + + @Autowired(required = true) + protected IConfiguration authConfig; + @Autowired(required = true) + private ProcessEngine processEngine; + @Autowired(required = true) + private IRequestStorage requestStoreage; + @Autowired(required = true) + protected IRevisionLogger revisionsLogger; + @Autowired(required = false) + protected ISsoManager ssoManager; + @Autowired + ModuleRegistration moduleRegistration; + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eaaf.core.impl.idp.auth.IAuthenticationManager# + * addParameterNameToWhiteList(java.lang .String) + */ + @Override + public final void addParameterNameToWhiteList(final String httpReqParam) { + if (StringUtils.isNotEmpty(httpReqParam)) { + reqParameterWhiteListeForModules.add(httpReqParam); + } + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eaaf.core.impl.idp.auth.IAuthenticationManager# + * addHeaderNameToWhiteList(java.lang. String) + */ + @Override + public final void addHeaderNameToWhiteList(final String httpReqParam) { + if (StringUtils.isNotEmpty(httpReqParam)) { + reqHeaderWhiteListeForModules.add(httpReqParam.toLowerCase()); + } + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eaaf.core.impl.idp.auth.IAuthenticationManager# + * addHeaderNameToWhiteList(java.lang. String) + */ + @Override + public final boolean doAuthentication(final HttpServletRequest httpReq, + final HttpServletResponse httpResp, final IRequest pendingReq) throws EaafException { + + if (!(pendingReq instanceof RequestImpl)) { + log.error("Requests that need authentication MUST be of type 'RequestImpl'"); + throw new RuntimeException( + "Requests that need authentication HAS TO BE of type 'RequestImpl'"); + + } + + // load OA configuration from pending request + final ISpConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); + + // set logging context and log unique OA identifier to revision log + TransactionIdUtils.setServiceProviderId(oaParam.getUniqueIdentifier()); + revisionsLogger.logEvent(pendingReq, EVENT_AUTHENTICATION_PROCESS_FOR_SP, + pendingReq.getSpEntityId()); + + // generic authentication request validation + if (pendingReq.isPassiv() && pendingReq.forceAuth()) { + // conflict! + throw new NoPassivAuthenticationException(); + } + + // check Single Sign-On functionality if SSOManager is available + boolean isValidSsoSession = false; + if (ssoManager != null) { + log.trace("SSOManager is loaded. Starting SSO session validation ... "); + // check if SSO is allowed for this service provider + ssoManager.isSsoAllowedForSp(pendingReq, httpReq); + + // check if SSO session is active and valid + isValidSsoSession = ssoManager.checkAndValidateSsoSession(pendingReq, httpReq, httpResp) + && pendingReq.needSingleSignOnFunctionality(); + + } + + // check if session is already authenticated + // boolean isSessionAuthenticated = tryPerformAuthentication((RequestImpl) + // pendingReq, + // isValidSSOSession); + // boolean isSessionAuthenticated = isValidSSOSession && + // StringUtils.isNotEmpty(pendingReq.getSSOSessionIdentifier()); + + // force new authentication authentication process + if (pendingReq.forceAuth()) { + startAuthenticationProcess(httpReq, (RequestImpl) pendingReq); + return false; + + // perform SSO-Consents evaluation if it it required + } else if (isValidSsoSession && pendingReq.isNeedUserConsent()) { + sendSingleSignOnConsentsEvaluation((RequestImpl) pendingReq); + return false; + + } else if (pendingReq.isPassiv()) { + if (isValidSsoSession + && StringUtils.isNotEmpty(pendingReq.getInternalSsoSessionIdentifier())) { + // Passive authentication ok! --> Populate pending request from SSO session + ssoManager.populatePendingRequestWithSsoInformation(pendingReq); + revisionsLogger.logEvent(pendingReq, EVENT_AUTHENTICATION_PROCESS_FINISHED); + return true; + + } else { + throw new NoPassivAuthenticationException(); + + } + + } else { + if (isValidSsoSession + && StringUtils.isNotEmpty(pendingReq.getInternalSsoSessionIdentifier())) { + // Is authenticated .. proceed + ssoManager.populatePendingRequestWithSsoInformation(pendingReq); + revisionsLogger.logEvent(pendingReq, EVENT_AUTHENTICATION_PROCESS_FINISHED); + return true; + + } else { + // Start authentication! + startAuthenticationProcess(httpReq, (RequestImpl) pendingReq); + return false; + + } + } + } + + @Override + public final void performOnlyIdpLogOut(final HttpServletRequest request, + final HttpServletResponse response, final IRequest pendingReq) { + + log.debug("Close session. Remove pending request ... "); + requestStoreage.removePendingRequest(pendingReq.getPendingRequestId()); + + if (ssoManager != null) { + try { + log.trace("'SSOManager' active. Search for active SSO sessions ... "); + if (ssoManager.destroySsoSessionOnIdpOnly(request, response, pendingReq)) { + log.info("SSO session successfully closed"); + } else { + log.info("Closing SSO session NOT successfully"); + } + + } catch (final EaafSsoException e) { + log.warn("Destroying of SSO session FAILED. Reason: " + e.getMessage(), e); + + } + + } + + } + + /** + * Populate process execution context and start process engine. + * + * @param httpReq http request + * @param pendingReq current pending request + * @throws ServletException In case of a servlet error + * @throws IOException In case of an IO error + * @throws EaafException In case of EAAF processing error + */ + private void startAuthenticationProcess(final HttpServletRequest httpReq, + final RequestImpl pendingReq) throws EaafException { + + log.info("Starting authentication ..."); + revisionsLogger.logEvent(pendingReq, EVENT_AUTHENTICATION_PROCESS_STARTED); + + // create authentication process execution context + final ExecutionContext executionContext = new ExecutionContextImpl(); + + // set oaIdentifeir + executionContext.put(EaafConstants.PROCESS_ENGINE_SERVICE_PROVIDER_ENTITYID, + pendingReq.getServiceProviderConfiguration().getUniqueIdentifier()); + + // add X509 SSL client certificate if exist + if (httpReq.getAttribute("javax.servlet.request.X509Certificate") != null) { + log.debug("Find SSL-client-certificate on request --> Add it to context"); + executionContext.put(EaafConstants.PROCESS_ENGINE_SSL_CLIENT_CERTIFICATE, + (X509Certificate[]) httpReq.getAttribute("javax.servlet.request.X509Certificate")); + pendingReq.setRawDataToTransaction(EaafConstants.PROCESS_ENGINE_SSL_CLIENT_CERTIFICATE, + httpReq.getAttribute("javax.servlet.request.X509Certificate")); + + } + + // add additional http request parameter to context + if (!reqParameterWhiteListeForModules.isEmpty()) { + final Enumeration<String> reqParamNames = httpReq.getParameterNames(); + while (reqParamNames.hasMoreElements()) { + final String paramName = reqParamNames.nextElement(); + if (StringUtils.isNotEmpty(paramName) + && reqParameterWhiteListeForModules.contains(paramName)) { + executionContext.put(paramName, + StringEscapeUtils.escapeHtml4(httpReq.getParameter(paramName))); + } + } + } + + // add additional http request parameter to context + if (!reqHeaderWhiteListeForModules.isEmpty()) { + final Enumeration<String> reqHeaderNames = httpReq.getHeaderNames(); + while (reqHeaderNames.hasMoreElements()) { + final String paramName = reqHeaderNames.nextElement(); + if (StringUtils.isNotEmpty(paramName) && at.gv.egiz.eaaf.core.impl.utils.ArrayUtils + .containsCaseInsensitive(paramName, reqHeaderWhiteListeForModules) + // reqHeaderWhiteListeForModules.contains(paramName.toLowerCase()) + ) { + executionContext.put(paramName.toLowerCase(), + StringEscapeUtils.escapeHtml4(httpReq.getHeader(paramName))); + } + + } + } + + // populate more IDP specific information to execution context + populateExecutionContext(executionContext, pendingReq, httpReq); + + // start process engine + startProcessEngine(pendingReq, executionContext); + + } + + /** + * Add additional parameters into context of process-engine. + * + * @param executionContext Process-engine context + * @param pendingReq Current pending request + * @param httpReq http request + * + * @throws EaafException In case of an error + */ + protected abstract void populateExecutionContext(ExecutionContext executionContext, + RequestImpl pendingReq, HttpServletRequest httpReq) throws EaafException; + + /** + * Starting a user consent evaluation. + * + * @param pendingReq current pending request + * @throws ServletException In case of a servlet error + * @throws IOException In case of an IO error + * @throws EaafException In case of a EAAF processing error + */ + private void sendSingleSignOnConsentsEvaluation(final RequestImpl pendingReq) throws EaafException { + + log.debug("Starting SSO user-consents evaluation ..."); + + // set authenticated flag to false, because user consents is required + pendingReq.setAuthenticated(false); + + // create execution context + final ExecutionContext executionContext = new ExecutionContextImpl(); + executionContext.put(ISsoManager.PROCESS_ENGINE_SSO_CONSENTS_EVALUATION, true); + + // start process engine + startProcessEngine(pendingReq, executionContext); + + } + + /** + * Select a specific process and starting process engine. + * + * @param pendingReq current pending request + * @param executionContext current context for process-engine + * @throws EaafException In case of an process-engine error + */ + private void startProcessEngine(final RequestImpl pendingReq, + final ExecutionContext executionContext) throws EaafException { + try { + // put pending-request ID on execurtionContext + executionContext.put(EaafConstants.PROCESS_ENGINE_PENDINGREQUESTID, + pendingReq.getPendingRequestId()); + + // create process instance + final String processDefinitionId = + moduleRegistration.selectProcess(executionContext, pendingReq); + + if (processDefinitionId == null) { + log.warn("No suitable process found for PendingReqId " + pendingReq.getPendingRequestId()); + throw new EaafException("process.02", new Object[] { pendingReq.getPendingRequestId() }); + + } + + final String processInstanceId = + processEngine.createProcessInstance(processDefinitionId, executionContext); + + // keep process instance id in protocol pending-request + pendingReq.setProcessInstanceId(processInstanceId); + + // store pending-request + requestStoreage.storePendingRequest(pendingReq); + + // start process + processEngine.start(pendingReq); + + } catch (final ProcessExecutionException e) { + final Throwable cause = e.getCause(); + if (cause != null && cause instanceof TaskExecutionException) { + final Throwable taskCause = cause.getCause(); + if (taskCause != null && taskCause instanceof EaafException) { + final EaafException moaTaskCause = (EaafException) taskCause; + log.warn(taskCause.getMessage(), taskCause); + throw moaTaskCause; + + } + } + + throw new EaafException("process.01", + new Object[] { pendingReq.getProcessInstanceId(), pendingReq.getPendingRequestId() }, e); + } + + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/RequestStorage.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/RequestStorage.java index e1598b8f..0834aa7c 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/RequestStorage.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/RequestStorage.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ + package at.gv.egiz.eaaf.core.impl.idp.auth; import org.apache.commons.lang3.StringUtils; @@ -34,185 +27,198 @@ import org.springframework.stereotype.Service; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IRequestStorage; -import at.gv.egiz.eaaf.core.api.idp.process.ProcessInstanceStoreDAO; +import at.gv.egiz.eaaf.core.api.idp.process.ProcessInstanceStoreDao; import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; @Service("RequestStorage") -public class RequestStorage implements IRequestStorage{ - private static final Logger log = LoggerFactory.getLogger(RequestStorage.class); - - @Autowired(required=true) ITransactionStorage transactionStorage; - @Autowired(required=true) ProcessInstanceStoreDAO processInstanceStore; - @Autowired(required=true) IPendingRequestIdGenerationStrategy pendingReqIdGenerationStrategy; - - @Override - public IRequest getPendingRequest(String pendingReqID) throws PendingReqIdValidationException { - - try { - final String internalPendingReqId = - pendingReqIdGenerationStrategy.validateAndGetPendingRequestId(pendingReqID); - log.debug("PendingReqId is valid"); - - //get pending-request from storage - final IRequest pendingRequest = getInternalPendingRequest(internalPendingReqId); - - //set transactionID and sessionID to Logger - TransactionIDUtils.setAllLoggingVariables(pendingRequest); - - return pendingRequest; - - } catch (final PendingReqIdValidationException e) { - log.info("PendingRequestId is invalid. Reason: {} ", e.getMessage()); - - // search invalid pending-request for errorHandling - IRequest invalidPendingRequest = null; - try { - if (StringUtils.isNotEmpty(e.getInvalidInternalPendingReqId())) - invalidPendingRequest = transactionStorage.get(e.getInvalidInternalPendingReqId(), IRequest.class); - - } catch (final EAAFException e1) { - log.info("No PendingRequst found with pendingRequestID " + pendingReqID); - return null; - - } - - e.setInvalidPendingReq(invalidPendingRequest); - throw e; - - } catch (EAAFException | NullPointerException e) { - log.info("No PendingRequst found with pendingRequestID " + pendingReqID); - return null; - - } - } - - @Override - public void storePendingRequest(IRequest pendingRequest) throws EAAFException { - try { - if (pendingRequest instanceof IRequest) { - try { - //validate pending-requestId - final String internalPendingRequestId = pendingReqIdGenerationStrategy.getPendingRequestIdWithOutChecks(pendingRequest.getPendingRequestId()); - - //store pending request - transactionStorage.put(internalPendingRequestId, pendingRequest, -1); - - } catch (final PendingReqIdValidationException e) { - log.warn("Invalid pending-request-Id. Reason: {}", e.getMessage()); - log.warn("Do NOT store pending-request with invalid pending-request-Id. The process will break soon!"); - - } - - } else - throw new EAAFException("PendigRequest is NOT of type 'IRequest'", null); - - } catch (final EAAFException e) { - log.warn("PendingRequest with ID=" + pendingRequest.getPendingRequestId() + - " can not stored.", e); - throw new EAAFStorageException("PendingRequest with Id: " + pendingRequest.getPendingRequestId() - + " can not be stored", e); - - } - - } - - @Override - public void removePendingRequest(String pendingReqID) { - - if (pendingReqID != null) { - String internalPendingReqId = null; - try { - internalPendingReqId = pendingReqIdGenerationStrategy.getPendingRequestIdWithOutChecks(pendingReqID); - - } catch (final PendingReqIdValidationException e) { - internalPendingReqId = e.getInvalidInternalPendingReqId(); - - } - - try { - //remove process-management execution instance# - if (internalPendingReqId != null) { - final IRequest pendingReq = getInternalPendingRequest(internalPendingReqId); - if (pendingReq != null && - pendingReq.getProcessInstanceId() != null) - processInstanceStore.remove(pendingReq.getProcessInstanceId()); - - //remove pending-request - transactionStorage.remove(internalPendingReqId); - } - - } catch (final EAAFException e) { - log.warn("Removing process associated with pending-request:" + pendingReqID + " FAILED.", e); - - } - - } - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.storage.IRequestStorage#changePendingRequestID(at.gv.egovernment.moa.id.moduls.IRequest) - */ - @Override - public String changePendingRequestID(IRequest pendingRequest) throws EAAFException { - if (pendingRequest instanceof RequestImpl) { - - //get old internal pendingReqId - String oldInternalRequestID = null; - try { - oldInternalRequestID = - pendingReqIdGenerationStrategy.getPendingRequestIdWithOutChecks(pendingRequest.getPendingRequestId()); - - } catch (final PendingReqIdValidationException e) { - //it's no problem, because it must be valid before when pending-request was loaded and we change it now - oldInternalRequestID = e.getInvalidInternalPendingReqId(); - - } - - - //generate new pendingReqId and get internalPendingReqId - final String newRequestID = pendingReqIdGenerationStrategy.generateExternalPendingRequestId(); - log.debug("Change pendingRequestID from " + pendingRequest.getPendingRequestId() + " to " + newRequestID); - ((RequestImpl)pendingRequest).setPendingRequestId(newRequestID); - - String newInternalPendingRequestId = null; - try { - newInternalPendingRequestId = pendingReqIdGenerationStrategy.getPendingRequestIdWithOutChecks(newRequestID); - - } catch (final PendingReqIdValidationException e) { - throw new EAAFException("internal.99", new Object[]{"Generate invalid pendingRequestId. Something looks WRONG"}, e); - - } - - - //change Key in cache - transactionStorage.changeKey(oldInternalRequestID, newInternalPendingRequestId, pendingRequest); - - //only delete oldRequestID, no change. - return newRequestID; - - } else { - log.error("PendingRequest object is not of type 'RequestImpl.class'"); - throw new EAAFException("PendingRequest object is not of type 'RequestImpl.class'", null); - - } - - } - - private IRequest getInternalPendingRequest(String internalPendingReqId) throws EAAFException { - final IRequest pendingRequest = transactionStorage.get(internalPendingReqId, IRequest.class); - if (pendingRequest == null) { - log.info("No PendingRequst found with pendingRequestID " + internalPendingReqId); - return null; - - } - - return pendingRequest; - - } +public class RequestStorage implements IRequestStorage { + private static final Logger log = LoggerFactory.getLogger(RequestStorage.class); + + @Autowired(required = true) + ITransactionStorage transactionStorage; + @Autowired(required = true) + ProcessInstanceStoreDao processInstanceStore; + @Autowired(required = true) + IPendingRequestIdGenerationStrategy pendingReqIdGenerationStrategy; + + @Override + public IRequest getPendingRequest(final String pendingReqID) + throws PendingReqIdValidationException { + + try { + final String internalPendingReqId = + pendingReqIdGenerationStrategy.validateAndGetPendingRequestId(pendingReqID); + log.debug("PendingReqId is valid"); + + // get pending-request from storage + final IRequest pendingRequest = getInternalPendingRequest(internalPendingReqId); + + // set transactionID and sessionID to Logger + TransactionIdUtils.setAllLoggingVariables(pendingRequest); + + return pendingRequest; + + } catch (final PendingReqIdValidationException e) { + log.info("PendingRequestId is invalid. Reason: {} ", e.getMessage()); + + // search invalid pending-request for errorHandling + IRequest invalidPendingRequest = null; + try { + if (StringUtils.isNotEmpty(e.getInvalidInternalPendingReqId())) { + invalidPendingRequest = + transactionStorage.get(e.getInvalidInternalPendingReqId(), IRequest.class); + } + + } catch (final EaafException e1) { + log.info("No PendingRequst found with pendingRequestID " + pendingReqID); + return null; + + } + + e.setInvalidPendingReq(invalidPendingRequest); + throw e; + + } catch (EaafException | NullPointerException e) { + log.info("No PendingRequst found with pendingRequestID " + pendingReqID); + return null; + + } + } + + @Override + public void storePendingRequest(final IRequest pendingRequest) throws EaafException { + try { + // validate pending-requestId + final String internalPendingRequestId = pendingReqIdGenerationStrategy + .getPendingRequestIdWithOutChecks(pendingRequest.getPendingRequestId()); + + // store pending request + transactionStorage.put(internalPendingRequestId, pendingRequest, -1); + + } catch (final PendingReqIdValidationException e) { + log.warn("Invalid pending-request-Id. Reason: {}", e.getMessage()); + log.warn( + "Do NOT store pending-request with invalid pending-request-Id. The process will break soon!"); + + } catch (final EaafException e) { + log.warn( + "PendingRequest with ID=" + pendingRequest.getPendingRequestId() + " can not stored.", e); + throw new EaafStorageException( + "PendingRequest with Id: " + pendingRequest.getPendingRequestId() + " can not be stored", + e); + + } + + } + + @Override + public void removePendingRequest(final String pendingReqID) { + + if (pendingReqID != null) { + String internalPendingReqId = null; + try { + internalPendingReqId = + pendingReqIdGenerationStrategy.getPendingRequestIdWithOutChecks(pendingReqID); + + } catch (final PendingReqIdValidationException e) { + internalPendingReqId = e.getInvalidInternalPendingReqId(); + + } + + try { + // remove process-management execution instance# + if (internalPendingReqId != null) { + final IRequest pendingReq = getInternalPendingRequest(internalPendingReqId); + if (pendingReq != null && pendingReq.getProcessInstanceId() != null) { + processInstanceStore.remove(pendingReq.getProcessInstanceId()); + } + + // remove pending-request + transactionStorage.remove(internalPendingReqId); + } + + } catch (final EaafException e) { + log.warn("Removing process associated with pending-request:" + pendingReqID + " FAILED.", + e); + + } + + } + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.storage.IRequestStorage#changePendingRequestID(at.gv + * .egovernment.moa. id.moduls.IRequest) + */ + @Override + public String changePendingRequestID(final IRequest pendingRequest) throws EaafException { + if (pendingRequest instanceof RequestImpl) { + + // get old internal pendingReqId + String oldInternalRequestID = null; + try { + oldInternalRequestID = pendingReqIdGenerationStrategy + .getPendingRequestIdWithOutChecks(pendingRequest.getPendingRequestId()); + + } catch (final PendingReqIdValidationException e) { + // it's no problem, because it must be valid before when pending-request was + // loaded and we + // change it now + oldInternalRequestID = e.getInvalidInternalPendingReqId(); + + } + + // generate new pendingReqId and get internalPendingReqId + final String newRequestID = pendingReqIdGenerationStrategy.generateExternalPendingRequestId(); + log.debug("Change pendingRequestID from " + pendingRequest.getPendingRequestId() + " to " + + newRequestID); + ((RequestImpl) pendingRequest).setPendingRequestId(newRequestID); + + String newInternalPendingRequestId = null; + try { + newInternalPendingRequestId = + pendingReqIdGenerationStrategy.getPendingRequestIdWithOutChecks(newRequestID); + + } catch (final PendingReqIdValidationException e) { + throw new EaafException("internal.99", + new Object[] { "Generate invalid pendingRequestId. Something looks WRONG" }, e); + + } + + // change Key in cache + transactionStorage.changeKey(oldInternalRequestID, newInternalPendingRequestId, + pendingRequest); + + // only delete oldRequestID, no change. + return newRequestID; + + } else { + log.error("PendingRequest object is not of type 'RequestImpl.class'"); + throw new EaafException("PendingRequest object is not of type 'RequestImpl.class'", null); + + } + + } + + private IRequest getInternalPendingRequest(final String internalPendingReqId) + throws EaafException { + final IRequest pendingRequest = transactionStorage.get(internalPendingReqId, IRequest.class); + if (pendingRequest == null) { + log.info("No PendingRequst found with pendingRequestID " + internalPendingReqId); + return null; + + } + + return pendingRequest; + + } } 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 2108e041..75b14489 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 @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.auth.builder; import java.io.ByteArrayInputStream; @@ -33,692 +26,757 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Map.Entry; -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; -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.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.IConfigurationWithSP; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +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.EAAFStorageException; +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.EaafStorageException; 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; - + +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; +import org.w3c.dom.Node; public abstract class AbstractAuthenticationDataBuilder implements IAuthenticationDataBuilder { - private static final Logger log = LoggerFactory.getLogger(AbstractAuthenticationDataBuilder.class); - - /** - * Identify authProcessData that should be directly mapped into authData - */ - public static final String GENERIC_AUTHDATA_IDENTIFIER = "authData_"; - - public static final String CONFIG_PROP_ENABLE_IDL_ATTRIBUTE_ESCAPEING = "configuration.bugfix.enable.idl.escaping"; - - protected Collection<String> includedToGenericAuthData = null; - @Autowired protected IConfigurationWithSP basicConfig; - - @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 ( final EAAFAuthenticationException e) { - throw e; - - } 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 <code>null</code> - * @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 <code>null</code> - * @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<String>(); - - //#################################################### - //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); - - - //set generic authProcessData to authdata - for (final Entry<String, Object> el : authProcessData.getGenericSessionDataStorage().entrySet()) { - if (el.getKey().startsWith(GENERIC_AUTHDATA_IDENTIFIER)) { - log.trace("Find generic authProcessData {}. Map it directly to authData", el.getKey()); - try { - internalAuthData.setGenericData(el.getKey(), el.getValue()); - - } catch (final EAAFStorageException e) { - log.warn("Can NOT set authData with key: {}", el.getKey(), null, e); - - } - - } - - } - - - } - - /** - * 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( - IConfigurationWithSP.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 <code>null</code> - * @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 && - !authProcessData.getGenericSessionDataStorage().isEmpty()) - includedToGenericAuthData = authProcessData.getGenericSessionDataStorage().keySet(); - else - includedToGenericAuthData = new ArrayList<String>(); - - //#################################################### - //set general authData info's - authData.setAuthenticationIssuer(pendingReq.getAuthURL()); - authData.setSsoSession(pendingReq.needSingleSignOnFunctionality()); - authData.setBaseIDTransferRestrication(pendingReq.getServiceProviderConfiguration().hasBaseIdTransferRestriction()); - - - //#################################################### - //parse user info's from identityLink - IIdentityLink idlFromPVPAttr = null; - final IIdentityLink identityLink = authProcessData.getIdentityLink(); - if (identityLink != null) { - parseBasicUserInfosFromIDL(authData, identityLink, includedToGenericAuthData); - - } else { - // identityLink is not direct in MOASession - 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 - + " --> Parse basic user info's from that attribute."); - InputStream idlStream = null; - try { - idlStream = new ByteArrayInputStream(Base64Utils.decodeFromString(pvpAttrIDL)); - idlFromPVPAttr = new SimpleIdentityLinkAssertionParser(idlStream).parseIdentityLink(); - parseBasicUserInfosFromIDL(authData, idlFromPVPAttr, includedToGenericAuthData); - - //set identitylink into AuthProcessData - authProcessData.setIdentityLink(idlFromPVPAttr);; - - } catch (final EAAFParserException e) { - log.warn("Received IdentityLink is not valid", e); - - } catch (final Exception e) { - log.warn("Received IdentityLink is not valid", e); - - } finally { - try { - includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_IDENTITY_LINK_NAME); - if (idlStream != null) - idlStream.close(); - - } catch (final IOException e) { - log.warn("Close InputStream FAILED.", e); - - } - } - } - - //if no basic user info's are set yet, parse info's single PVP-Attributes - if (StringUtils.isEmpty(authData.getFamilyName())) { - log.debug("No IdentityLink found or not parseable --> Parse basic user info's from single PVP-Attributes."); - authData.setFamilyName(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME, String.class)); - authData.setGivenName(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.GIVEN_NAME_NAME, String.class)); - authData.setDateOfBirth(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.BIRTHDATE_NAME, String.class)); - authData.setIdentificationValue(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_SOURCE_PIN_NAME, String.class)); - authData.setIdentificationType(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME, String.class)); - - //remove corresponding keys from genericSessionData if exists - includedToGenericAuthData.remove(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME); - includedToGenericAuthData.remove(PVPAttributeDefinitions.GIVEN_NAME_NAME); - includedToGenericAuthData.remove(PVPAttributeDefinitions.BIRTHDATE_NAME); - includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_NAME); - includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME); - } - - } - - if (authData.getIdentificationType() != null && - !authData.getIdentificationType().equals(EAAFConstants.URN_PREFIX_BASEID)) { - log.trace("IdentificationType is not a baseID --> clear it. "); - authData.setBPK(authData.getIdentificationValue()); - authData.setBPKType(authData.getIdentificationType()); - - authData.setIdentificationValue(null); - authData.setIdentificationType(null); - } - - - //#################################################### - //set QAA level - setQAALevel(authData, authProcessData, pendingReq); - - - //#################################################### - //set isForeigner flag - setFlagForeigner(authData, authProcessData, pendingReq); - - - //#################################################### - //set citizen country-code - setCitizenCountryCode(authData, authProcessData, pendingReq); - - - //#################################################### - // set bPK and IdentityLink - final String pvpbPKValue = getbPKValueFromPVPAttribute(authProcessData); - final String pvpbPKTypeAttr = getbPKTypeFromPVPAttribute(authProcessData); - final Pair<String, String> pvpEncbPKAttr = getEncryptedbPKFromPVPAttribute(authProcessData, authData, pendingReq.getServiceProviderConfiguration()); - - //check if a unique ID for this citizen exists - if (StringUtils.isEmpty(authData.getIdentificationValue()) && - StringUtils.isEmpty(pvpbPKValue) && StringUtils.isEmpty(authData.getBPK()) && - pvpEncbPKAttr == null) { - log.info("Can not build authData, because moaSession include no bPK, encrypted bPK or baseID"); - throw new EAAFBuilderException("builder.08", new Object[]{"No " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME - + " or " + PVPAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME - + " or " + PVPAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME}, - "No " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME - + " or " + PVPAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME - + " or " + PVPAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME); - - } - - //check if bPK already added to AuthData matches OA - if (StringUtils.isNotEmpty(authData.getBPK()) - && matchsReceivedbPKToOnlineApplication(pendingReq.getServiceProviderConfiguration(), authData.getBPKType()) ) { - log.debug("Correct bPK is already included in AuthData."); - - //check if bPK received by PVP-Attribute matches OA - } else if (StringUtils.isNotEmpty(pvpbPKValue) && - matchsReceivedbPKToOnlineApplication(pendingReq.getServiceProviderConfiguration(), pvpbPKTypeAttr)) { - log.debug("Receive correct bPK from PVP-Attribute"); - authData.setBPK(pvpbPKValue); - authData.setBPKType(pvpbPKTypeAttr); - - // baseID is in AuthSesson --> calculate bPK directly - } else if (StringUtils.isNotEmpty(authData.getIdentificationValue())) { - log.debug("Citizen baseID is in MOASession --> calculate bPK from this."); - final Pair<String, String> result = buildOAspecificbPK(pendingReq, authData); - authData.setBPK(result.getFirst()); - authData.setBPKType(result.getSecond()); - - //check if decrypted bPK exists - } else if (pvpEncbPKAttr != null) { - log.debug("Receive bPK as encrypted bPK and decryption was possible."); - authData.setBPK(pvpEncbPKAttr.getFirst()); - authData.setBPKType(pvpEncbPKAttr.getSecond()); - - //ask SZR to get bPK - } else { - String notValidbPK = authData.getBPK(); - String notValidbPKType = authData.getBPKType(); - if (StringUtils.isEmpty(notValidbPK) && - StringUtils.isEmpty(notValidbPKType)) { - notValidbPK = pvpbPKValue; - notValidbPKType = pvpbPKTypeAttr; - - if (StringUtils.isEmpty(notValidbPK) && - StringUtils.isEmpty(notValidbPKType)) { - log.error("No bPK in MOASession. THIS error should not occur any more."); - throw new NullPointerException("No bPK in MOASession. THIS error should not occur any more."); - } - } - - final Pair<String, String> 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()); - final Pair<String, String> result = buildOAspecificbPK(pendingReq, authData); - authData.setBPK(result.getFirst()); - authData.setBPKType(result.getSecond()); - - } else { - log.warn("Can not build authData, because moaSession include no valid bPK, encrypted bPK or sourceID"); - throw new EAAFBuilderException("builder.13", new Object[]{pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()}, - "No valid " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME - + " or " + PVPAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME - + " or " + PVPAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME); - - } - } - - //build IdentityLink - if (authProcessData.getIdentityLink() != null) - authData.setIdentityLink(buildOAspecificIdentityLink( - pendingReq.getServiceProviderConfiguration(), - authProcessData.getIdentityLink(), - authData.getBPK(), - authData.getBPKType())); - else - log.info("Can NOT set IdentityLink. Msg: No IdentityLink found"); - - } - - //extract a encrypted bPK from PVP attrobute - @Deprecated - protected abstract Pair<String, String> getEncryptedbPKFromPVPAttribute(IAuthProcessDataContainer authProcessDataContainer, - AuthenticationData authData, ISPConfiguration spConfig) throws EAAFBuilderException; - - //request baseId from SRZ - @Deprecated - protected abstract Pair<String, String> getbaseIDFromSZR(AuthenticationData authData, String notValidbPK, - String notValidbPKType); - - @Deprecated - protected Pair<String, String> buildOAspecificbPK(IRequest pendingReq, AuthenticationData authData) throws EAAFBuilderException { - final ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); - - final String baseID = authData.getIdentificationValue(); - final String baseIDType = authData.getIdentificationType(); - Pair<String, String> sectorSpecId = null; - - if (EAAFConstants.URN_PREFIX_BASEID.equals(baseIDType)) { - //SAML1 legacy target parameter work-around - final String spTargetId = oaParam.getAreaSpecificTargetIdentifier(); - log.debug("Use OA target identifier '" + spTargetId + "' from configuration"); - - //calculate sector specific unique identifier - sectorSpecId = new BPKBuilder().generateAreaSpecificPersonIdentifier(baseID, spTargetId); - - } else { - log.error("!!!baseID-element does not include a baseID. This should not be happen any more!!!"); - sectorSpecId = Pair.newInstance(baseID, baseIDType); - - } - - log.trace("Authenticate user with bPK:" + sectorSpecId.getFirst() + " Type:" + sectorSpecId.getSecond()); - return sectorSpecId; - - } - - @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 ..."); - final Element idlassertion = idl.getSamlAssertion(); - //set bpk/wpbk; - final Node prIdentification = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); - prIdentification.getFirstChild().setNodeValue(bPK); - //set bkp/wpbk type - final Node prIdentificationType = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_TYPE_XPATH); - prIdentificationType.getFirstChild().setNodeValue(bPKType); - - final SimpleIdentityLinkAssertionParser idlparser = new SimpleIdentityLinkAssertionParser(idlassertion); - return idlparser.parseIdentityLink(); - - } else - return idl; - - } - - /** - * Check a bPK-Type against a Service-Provider configuration <br> - * If bPK-Type is <code>null</code> the result is <code>false</code>. - * - * @param oaParam Service-Provider configuration, never null - * @param bPKType bPK-Type to check - * @return true, if bPK-Type matchs to Service-Provider configuration, otherwise false - */ - @Deprecated - protected boolean matchsReceivedbPKToOnlineApplication(ISPConfiguration oaParam, String bPKType) { - return oaParam.getAreaSpecificTargetIdentifier().equals(bPKType); - - } - - /** - * Parse information from an IdentityLink into AuthData object - * - * @param authData - * @param identityLink - * @param includedGenericSessionData - */ - @Deprecated - private void parseBasicUserInfosFromIDL(AuthenticationData authData, IIdentityLink identityLink, Collection<String> includedGenericSessionData) { - authData.setIdentificationValue(identityLink.getIdentificationValue()); - authData.setIdentificationType(identityLink.getIdentificationType()); - - /* GivenNames and FamilyNames with simple Apostrophe were escaped with ' - * in IdentityLinkParser since 5 years. This feature was bug-fix for an SL1.0 AuthBlock problem. - * However, the authentication attributes (SAML2, eIDAS, OpenID-Connect) also includes this escaped values, - * but there it is not neccesary. We fix this problem in 3.4.3, but the fix can be deactivated - * for dependency reasons. - */ - if (basicConfig.getBasicConfigurationBoolean(CONFIG_PROP_ENABLE_IDL_ATTRIBUTE_ESCAPEING, false)) { - authData.setGivenName(identityLink.getGivenName().replaceAll("'", "'")); - authData.setFamilyName(identityLink.getFamilyName().replaceAll("'", "'")); - - } else { - authData.setGivenName(identityLink.getGivenName()); - authData.setFamilyName(identityLink.getFamilyName()); - - } - - authData.setDateOfBirth(identityLink.getDateOfBirth()); - - - //remove corresponding keys from genericSessionData if exists - includedGenericSessionData.remove(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME); - includedGenericSessionData.remove(PVPAttributeDefinitions.GIVEN_NAME_NAME); - includedGenericSessionData.remove(PVPAttributeDefinitions.BIRTHDATE_NAME); - includedGenericSessionData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_NAME); - includedGenericSessionData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME); - - } - - /** - * Get bPK from PVP Attribute 'BPK_NAME', which could be exist in - * MOASession as 'GenericData' <br> <pre><code>session.getGenericDataFromSession(PVPConstants.BPK_NAME, String.class)</code></pre> - * - * @param session MOASession, but never null - * @return bPK, which was received by PVP-Attribute, or <code>null</code> if no attribute exists - */ - @Deprecated - private String getbPKValueFromPVPAttribute(IAuthProcessDataContainer session) { - String pvpbPKValueAttr = session.getGenericDataFromSession(PVPAttributeDefinitions.BPK_NAME, String.class); - if (StringUtils.isNotEmpty(pvpbPKValueAttr)) { - - //fix a wrong bPK-value prefix, which was used in some PVP Standardportal implementations - if (pvpbPKValueAttr.startsWith("bPK:")) { - log.warn("Attribute " + PVPAttributeDefinitions.BPK_NAME - + " contains a not standardize prefix! Staring attribute value correction process ..."); - pvpbPKValueAttr = pvpbPKValueAttr.substring("bPK:".length()); - - } - - final String[] spitted = pvpbPKValueAttr.split(":"); - if (spitted.length == 2) { - log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME); - return spitted[1]; - - - - } else if (spitted.length > 2) { - log.warn("Attribute " + PVPAttributeDefinitions.BPK_NAME + " has a wrong encoding and can NOT be USED!" - + " Value:" + pvpbPKValueAttr); - return null; - - } else { - log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME + " without prefix. Use it as it is"); - return spitted[0]; - - } - - } - - return null; - } - - /** - * Get bPK-Type from PVP Attribute 'EID_SECTOR_FOR_IDENTIFIER_NAME', which could be exist in - * MOASession as 'GenericData' <br> <pre><code>session.getGenericDataFromSession(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME, String.class)</code></pre> - * - * @param session MOASession, but never null - * @return bPKType, which was received by PVP-Attribute, or <code>null</code> if no attribute exists - */ - @Deprecated - private String getbPKTypeFromPVPAttribute(IAuthProcessDataContainer session) { - 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 -// if (pvpbPKTypeAttr.startsWith(EAAFConstants.URN_PREFIX_CDID) && -// !pvpbPKTypeAttr.substring(EAAFConstants.URN_PREFIX_CDID.length(), -// EAAFConstants.URN_PREFIX_CDID.length() + 1).equals("+")) { -// log.warn("Receive uncorrect encoded bBKType attribute " + pvpbPKTypeAttr + " Starting attribute value correction ... "); -// pvpbPKTypeAttr = EAAFConstants.URN_PREFIX_CDID + "+" + pvpbPKTypeAttr.substring(EAAFConstants.URN_PREFIX_CDID.length() + 1); -// -// } - log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME); - return pvpbPKTypeAttr; - } - - return null; - - - /* - * INFO: This code could be used to extract the bPKType from 'PVPConstants.BPK_NAME', - * because the prefix of BPK_NAME attribute contains the postfix of the bPKType - * - * Now, all PVP Standardportals should be able to send 'EID_SECTOR_FOR_IDENTIFIER' - * PVP attributes - */ -// String pvpbPKValueAttr = session.getGenericDataFromSession(PVPConstants.BPK_NAME, String.class); -// String[] spitted = pvpbPKValueAttr.split(":"); -// if (MiscUtil.isEmpty(authData.getBPKType())) { -// Logger.debug("PVP assertion contains NO bPK/wbPK target attribute. " + -// "Starting target extraction from bPK/wbPK prefix ..."); -// //exract bPK/wbPK type from bpk attribute value prefix if type is -// //not transmitted as single attribute -// Pattern pattern = Pattern.compile("[a-zA-Z]{2}(-[a-zA-Z]+)?"); -// Matcher matcher = pattern.matcher(spitted[0]); -// if (matcher.matches()) { -// //find public service bPK -// authData.setBPKType(Constants.URN_PREFIX_CDID + "+" + spitted[0]); -// Logger.debug("Found bPK prefix. Set target to " + authData.getBPKType()); -// -// } else { -// //find business service wbPK -// authData.setBPKType(Constants.URN_PREFIX_WBPK+ "+" + spitted[0]); -// Logger.debug("Found wbPK prefix. Set target to " + authData.getBPKType()); -// -// } -// } - - } + private static final Logger log = + LoggerFactory.getLogger(AbstractAuthenticationDataBuilder.class); + + /** + * Identify authProcessData that should be directly mapped into authData. + */ + public static final String GENERIC_AUTHDATA_IDENTIFIER = "authData_"; + + public static final String CONFIG_PROP_ENABLE_IDL_ATTRIBUTE_ESCAPEING = + "configuration.bugfix.enable.idl.escaping"; + + protected Collection<String> includedToGenericAuthData = null; + @Autowired + protected IConfigurationWithSP basicConfig; + + @Override + public IAuthData buildAuthenticationData(final 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 (final EaafAuthenticationException e) { + throw e; + + } 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 <code>null</code> + * @throws EaafException In case of an error + */ + @NonNull + protected abstract 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 <code>null</code> + * @throws EaafException In case of an error + */ + protected abstract void buildServiceSpecificAuthenticationData(IAuthData authData, + IRequest pendingReq) throws EaafException; + + /** + * Add generic E-ID information into already existing AuthData. + * + * @param authData AuthData object + * @param authProcessData Authentication information holder from current pending + * request + * @param pendingReq current pending request + * @throws EaafAuthenticationException In case inconsistent authentication data + */ + private void buildInternalAuthDataGeneric(@NonNull final IAuthData authData, + @NonNull final IAuthProcessDataContainer authProcessData, + @NonNull final IRequest pendingReq) throws EaafAuthenticationException { + 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(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, String.class)); + internalAuthData.setGivenName(authProcessData + .getGenericDataFromSession(PvpAttributeDefinitions.GIVEN_NAME_NAME, String.class)); + internalAuthData.setDateOfBirth(authProcessData + .getGenericDataFromSession(PvpAttributeDefinitions.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); + + // #################################################### + // set isForeigner flag + setFlagForeigner(internalAuthData, authProcessData); + + // #################################################### + // set citizen country-code + setCitizenCountryCode(internalAuthData, authProcessData); + + // set generic authProcessData to authdata + for (final Entry<String, Object> el : authProcessData.getGenericSessionDataStorage() + .entrySet()) { + if (el.getKey().startsWith(GENERIC_AUTHDATA_IDENTIFIER)) { + log.trace("Find generic authProcessData {}. Map it directly to authData", el.getKey()); + try { + internalAuthData.setGenericData(el.getKey(), el.getValue()); + + } catch (final EaafStorageException e) { + log.warn("Can NOT set authData with key: {}", el.getKey(), null, e); + + } + + } + + } + + } + + /** + * Parse citzen country-code into AuthData. + * + * @param authData Current authentication data + * @param authProcessData Authentication information holder from current pending + * request + * @throws EaafAuthenticationException In case inconsistent authentication data + */ + private void setCitizenCountryCode(final AuthenticationData authData, + final IAuthProcessDataContainer authProcessData) throws EaafAuthenticationException { + 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()) { + log.warn("EID_Issuing_Nation NOT SET for foreign citizen."); + throw new EaafAuthenticationException("builder.11", + new Object[] { "EID_Issuing_Nation NOT SET for foreign citizen." }); + + } else { + authData.setCiticenCountryCode(basicConfig.getBasicConfiguration( + IConfigurationWithSP.CONFIG_PROPS_AUTH_DEFAULT_COUNTRYCODE, + EaafConstants.COUNTRYCODE_AUSTRIA)); + + } + } + + } + + /** + * parse QAA Level into AuthData. + * + * @param authData current authentication data + * @param authProcessData Authentication information holder from current pending + * request + * @param pendingReq current pending request + */ + private void setQaaLevel(@NonNull final AuthenticationData authData, + @NonNull final IAuthProcessDataContainer authProcessData) { + 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); + + } + + } + + private void setFlagForeigner(final AuthenticationData authData, + final IAuthProcessDataContainer authProcessData) { + // 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 <code>null</code> + * @throws EaafException In case of an error + */ + @Deprecated + @NonNull + protected abstract IAuthData buildDeprecatedAuthData(IRequest pendingReq) throws EaafException; + + @Deprecated + protected void generateDeprecatedBasicAuthData(final AuthenticationData authData, + final IRequest pendingReq, final IAuthProcessDataContainer authProcessData) + throws EaafBuilderException, EaafConfigurationException, XPathException, DOMException, + EaafParserException, EaafAuthenticationException { + + if (authProcessData.getGenericSessionDataStorage() != null + && !authProcessData.getGenericSessionDataStorage().isEmpty()) { + includedToGenericAuthData = authProcessData.getGenericSessionDataStorage().keySet(); + } else { + includedToGenericAuthData = new ArrayList<>(); + } + + // #################################################### + // set general authData info's + authData.setAuthenticationIssuer(pendingReq.getAuthUrl()); + authData.setSsoSession(pendingReq.needSingleSignOnFunctionality()); + authData.setBaseIdTransferRestrication( + pendingReq.getServiceProviderConfiguration().hasBaseIdTransferRestriction()); + + // #################################################### + // parse user info's from identityLink + IIdentityLink idlFromPvpAttr = null; + final IIdentityLink identityLink = authProcessData.getIdentityLink(); + if (identityLink != null) { + parseBasicUserInfosFromIdl(authData, identityLink, includedToGenericAuthData); + + } else { + // identityLink is not direct in MOASession + 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 + + " --> Parse basic user info's from that attribute."); + InputStream idlStream = null; + try { + idlStream = new ByteArrayInputStream(Base64Utils.decodeFromString(pvpAttrIdl)); + idlFromPvpAttr = new SimpleIdentityLinkAssertionParser(idlStream).parseIdentityLink(); + parseBasicUserInfosFromIdl(authData, idlFromPvpAttr, includedToGenericAuthData); + + // set identitylink into AuthProcessData + authProcessData.setIdentityLink(idlFromPvpAttr); + + } catch (final EaafParserException e) { + log.warn("Received IdentityLink is not valid", e); + + } catch (final Exception e) { + log.warn("Received IdentityLink is not valid", e); + + } finally { + try { + includedToGenericAuthData.remove(PvpAttributeDefinitions.EID_IDENTITY_LINK_NAME); + if (idlStream != null) { + idlStream.close(); + } + + } catch (final IOException e) { + log.warn("Close InputStream FAILED.", e); + + } + } + } + + // if no basic user info's are set yet, parse info's single PVP-Attributes + if (StringUtils.isEmpty(authData.getFamilyName())) { + log.debug( + "No IdentityLink found or not parseable --> Parse basic user info's from single PVP-Attributes."); + authData.setFamilyName(authProcessData + .getGenericDataFromSession(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, String.class)); + authData.setGivenName(authProcessData + .getGenericDataFromSession(PvpAttributeDefinitions.GIVEN_NAME_NAME, String.class)); + authData.setDateOfBirth(authProcessData + .getGenericDataFromSession(PvpAttributeDefinitions.BIRTHDATE_NAME, String.class)); + authData.setIdentificationValue(authProcessData + .getGenericDataFromSession(PvpAttributeDefinitions.EID_SOURCE_PIN_NAME, String.class)); + authData.setIdentificationType(authProcessData.getGenericDataFromSession( + PvpAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME, String.class)); + + // remove corresponding keys from genericSessionData if exists + includedToGenericAuthData.remove(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME); + includedToGenericAuthData.remove(PvpAttributeDefinitions.GIVEN_NAME_NAME); + includedToGenericAuthData.remove(PvpAttributeDefinitions.BIRTHDATE_NAME); + includedToGenericAuthData.remove(PvpAttributeDefinitions.EID_SOURCE_PIN_NAME); + includedToGenericAuthData.remove(PvpAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME); + } + + } + + if (authData.getIdentificationType() != null + && !authData.getIdentificationType().equals(EaafConstants.URN_PREFIX_BASEID)) { + log.trace("IdentificationType is not a baseID --> clear it. "); + authData.setBpk(authData.getIdentificationValue()); + authData.setBpkType(authData.getIdentificationType()); + + authData.setIdentificationValue(null); + authData.setIdentificationType(null); + } + + // #################################################### + // set QAA level + setQaaLevel(authData, authProcessData); + + // #################################################### + // set isForeigner flag + setFlagForeigner(authData, authProcessData); + + // #################################################### + // set citizen country-code + setCitizenCountryCode(authData, authProcessData); + + // #################################################### + // set bPK and IdentityLink + final String pvpBpkValue = getBpkValueFromPvpAttribute(authProcessData); + final String pvpBpkTypeAttr = getBpkTypeFromPvpAttribute(authProcessData); + final Pair<String, String> pvpEncBpkAttr = getEncryptedBpkFromPvpAttribute(authProcessData, + authData, pendingReq.getServiceProviderConfiguration()); + + // check if a unique ID for this citizen exists + if (StringUtils.isEmpty(authData.getIdentificationValue()) && StringUtils.isEmpty(pvpBpkValue) + && StringUtils.isEmpty(authData.getBpk()) && pvpEncBpkAttr == null) { + log.info( + "Can not build authData, because session include no bPK, encrypted bPK or baseID"); + throw new EaafBuilderException("builder.08", + new Object[] { "No " + PvpAttributeDefinitions.BPK_FRIENDLY_NAME + " or " + + PvpAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME + " or " + + PvpAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME }, + "No " + PvpAttributeDefinitions.BPK_FRIENDLY_NAME + " or " + + PvpAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME + " or " + + PvpAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME); + + } + + // check if bPK already added to AuthData matches OA + if (StringUtils.isNotEmpty(authData.getBpk()) && matchsReceivedBpkToOnlineApplication( + pendingReq.getServiceProviderConfiguration(), authData.getBpkType())) { + log.debug("Correct bPK is already included in AuthData."); + + // check if bPK received by PVP-Attribute matches OA + } else if (StringUtils.isNotEmpty(pvpBpkValue) && matchsReceivedBpkToOnlineApplication( + pendingReq.getServiceProviderConfiguration(), pvpBpkTypeAttr)) { + log.debug("Receive correct bPK from PVP-Attribute"); + authData.setBpk(pvpBpkValue); + authData.setBpkType(pvpBpkTypeAttr); + + // baseID is in AuthSesson --> calculate bPK directly + } else if (StringUtils.isNotEmpty(authData.getIdentificationValue())) { + log.debug("Citizen baseID is in AuthSession --> calculate bPK from this."); + final Pair<String, String> result = buildOAspecificbPK(pendingReq, authData); + authData.setBpk(result.getFirst()); + authData.setBpkType(result.getSecond()); + + // check if decrypted bPK exists + } else if (pvpEncBpkAttr != null) { + log.debug("Receive bPK as encrypted bPK and decryption was possible."); + authData.setBpk(pvpEncBpkAttr.getFirst()); + authData.setBpkType(pvpEncBpkAttr.getSecond()); + + // ask SZR to get bPK + } else { + String notValidbPK = authData.getBpk(); + String notValidBpkType = authData.getBpkType(); + if (StringUtils.isEmpty(notValidbPK) && StringUtils.isEmpty(notValidBpkType)) { + notValidbPK = pvpBpkValue; + notValidBpkType = pvpBpkTypeAttr; + + if (StringUtils.isEmpty(notValidbPK) && StringUtils.isEmpty(notValidBpkType)) { + log.error("No bPK in AuthSession. THIS error should not occur any more."); + throw new NullPointerException( + "No bPK in AuthSession. THIS error should not occur any more."); + } + } + + final Pair<String, String> 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()); + final Pair<String, String> result = buildOAspecificbPK(pendingReq, authData); + authData.setBpk(result.getFirst()); + authData.setBpkType(result.getSecond()); + + } else { + log.warn( + "Can not build authData, because moaSession include no valid bPK, encrypted bPK or sourceID"); + throw new EaafBuilderException("builder.13", + new Object[] { + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier() }, + "No valid " + PvpAttributeDefinitions.BPK_FRIENDLY_NAME + " or " + + PvpAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME + " or " + + PvpAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME); + + } + } + + // build IdentityLink + if (authProcessData.getIdentityLink() != null) { + authData + .setIdentityLink(buildOAspecificIdentityLink(pendingReq.getServiceProviderConfiguration(), + authProcessData.getIdentityLink(), authData.getBpk(), authData.getBpkType())); + } else { + log.info("Can NOT set IdentityLink. Msg: No IdentityLink found"); + } + + } + + // extract a encrypted bPK from PVP attrobute + @Deprecated + protected abstract Pair<String, String> getEncryptedBpkFromPvpAttribute( + IAuthProcessDataContainer authProcessDataContainer, AuthenticationData authData, + ISpConfiguration spConfig) throws EaafBuilderException; + + // request baseId from SRZ + @Deprecated + protected abstract Pair<String, String> getbaseIdFromSzr(AuthenticationData authData, + String notValidBpk, String notValidBpkType); + + @Deprecated + protected Pair<String, String> buildOAspecificbPK(final IRequest pendingReq, + final AuthenticationData authData) throws EaafBuilderException { + final ISpConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); + + final String baseID = authData.getIdentificationValue(); + final String baseIdType = authData.getIdentificationType(); + Pair<String, String> sectorSpecId = null; + + if (EaafConstants.URN_PREFIX_BASEID.equals(baseIdType)) { + // SAML1 legacy target parameter work-around + final String spTargetId = oaParam.getAreaSpecificTargetIdentifier(); + log.debug("Use OA target identifier '" + spTargetId + "' from configuration"); + + new BpkBuilder(); + // calculate sector specific unique identifier + sectorSpecId = BpkBuilder.generateAreaSpecificPersonIdentifier(baseID, spTargetId); + + } else { + log.error( + "!!!baseID-element does not include a baseID. This should not be happen any more!!!"); + sectorSpecId = Pair.newInstance(baseID, baseIdType); + + } + + log.trace("Authenticate user with bPK:" + sectorSpecId.getFirst() + " Type:" + + sectorSpecId.getSecond()); + return sectorSpecId; + + } + + @Deprecated + protected IIdentityLink buildOAspecificIdentityLink(final ISpConfiguration spConfig, + final IIdentityLink idl, final String bpk, final String bpkType) + throws EaafConfigurationException, XPathException, DOMException, EaafParserException { + if (spConfig.hasBaseIdTransferRestriction()) { + log.debug("SP: " + spConfig.getUniqueIdentifier() + + " has baseId transfer restriction. Remove baseId from IDL ..."); + final Element idlassertion = idl.getSamlAssertion(); + // set bpk/wpbk; + final Node prIdentification = XPathUtils.selectSingleNode(idlassertion, + SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); + prIdentification.getFirstChild().setNodeValue(bpk); + // set bkp/wpbk type + final Node prIdentificationType = XPathUtils.selectSingleNode(idlassertion, + SimpleIdentityLinkAssertionParser.PERSON_IDENT_TYPE_XPATH); + prIdentificationType.getFirstChild().setNodeValue(bpkType); + + final SimpleIdentityLinkAssertionParser idlparser = + new SimpleIdentityLinkAssertionParser(idlassertion); + return idlparser.parseIdentityLink(); + + } else { + return idl; + } + + } + + /** + * Check a bPK-Type against a Service-Provider configuration <br> + * If bPK-Type is <code>null</code> the result is <code>false</code>. + * + * @param oaParam Service-Provider configuration, never null + * @param bpkType bPK-Type to check + * @return true, if bPK-Type matchs to Service-Provider configuration, otherwise + * false + */ + @Deprecated + protected boolean matchsReceivedBpkToOnlineApplication(final ISpConfiguration oaParam, + final String bpkType) { + return oaParam.getAreaSpecificTargetIdentifier().equals(bpkType); + + } + + /** + * Parse information from an IdentityLink into AuthData object. + * + * @param authData current authentication data + * @param identityLink User's identityLink + * @param includedGenericSessionData Generic AuthSession Data from PVP + * attributes + */ + @Deprecated + private void parseBasicUserInfosFromIdl(final AuthenticationData authData, + final IIdentityLink identityLink, final Collection<String> includedGenericSessionData) { + authData.setIdentificationValue(identityLink.getIdentificationValue()); + authData.setIdentificationType(identityLink.getIdentificationType()); + + /* + * GivenNames and FamilyNames with simple Apostrophe were escaped with ' in + * IdentityLinkParser since 5 years. This feature was bug-fix for an SL1.0 + * AuthBlock problem. However, the authentication attributes (SAML2, eIDAS, + * OpenID-Connect) also includes this escaped values, but there it is not + * neccesary. We fix this problem in 3.4.3, but the fix can be deactivated for + * dependency reasons. + */ + if (basicConfig.getBasicConfigurationBoolean(CONFIG_PROP_ENABLE_IDL_ATTRIBUTE_ESCAPEING, + false)) { + authData.setGivenName(identityLink.getGivenName().replaceAll("'", "'")); + authData.setFamilyName(identityLink.getFamilyName().replaceAll("'", "'")); + + } else { + authData.setGivenName(identityLink.getGivenName()); + authData.setFamilyName(identityLink.getFamilyName()); + + } + + authData.setDateOfBirth(identityLink.getDateOfBirth()); + + // remove corresponding keys from genericSessionData if exists + includedGenericSessionData.remove(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME); + includedGenericSessionData.remove(PvpAttributeDefinitions.GIVEN_NAME_NAME); + includedGenericSessionData.remove(PvpAttributeDefinitions.BIRTHDATE_NAME); + includedGenericSessionData.remove(PvpAttributeDefinitions.EID_SOURCE_PIN_NAME); + includedGenericSessionData.remove(PvpAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME); + + } + + /** + * Get bPK from PVP Attribute 'BPK_NAME', which could be exist in MOASession as + * 'GenericData'. <br> + * + * <pre> + * <code>session.getGenericDataFromSession(PVPConstants.BPK_NAME, String.class)</code> + * </pre> + * + * @param session MOASession, but never null + * @return bPK, which was received by PVP-Attribute, or <code>null</code> if no + * attribute exists + */ + @Deprecated + private String getBpkValueFromPvpAttribute(final IAuthProcessDataContainer session) { + String pvpBpkValueAttr = + session.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME, String.class); + if (StringUtils.isNotEmpty(pvpBpkValueAttr)) { + + // fix a wrong bPK-value prefix, which was used in some PVP Standardportal + // implementations + if (pvpBpkValueAttr.startsWith("bPK:")) { + log.warn("Attribute " + PvpAttributeDefinitions.BPK_NAME + + " contains a not standardize prefix! Staring attribute value correction process ..."); + pvpBpkValueAttr = pvpBpkValueAttr.substring("bPK:".length()); + + } + + final String[] spitted = pvpBpkValueAttr.split(":"); + if (spitted.length == 2) { + log.debug("Find PVP-Attr: " + PvpAttributeDefinitions.BPK_FRIENDLY_NAME); + return spitted[1]; + + } else if (spitted.length > 2) { + log.warn("Attribute " + PvpAttributeDefinitions.BPK_NAME + + " has a wrong encoding and can NOT be USED!" + " Value:" + pvpBpkValueAttr); + return null; + + } else { + log.debug("Find PVP-Attr: " + PvpAttributeDefinitions.BPK_FRIENDLY_NAME + + " without prefix. Use it as it is"); + return spitted[0]; + + } + + } + + return null; + } + + /** + * Get bPK-Type from PVP Attribute 'EID_SECTOR_FOR_IDENTIFIER_NAME', which could + * be exist in MOASession as 'GenericData'. <br> + * + * <pre> + * <code>session.getGenericDataFromSession(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME, String.class)</code> + * </pre> + * + * @param session MOASession, but never null + * @return bPKType, which was received by PVP-Attribute, or <code>null</code> if + * no attribute exists + */ + @Deprecated + private String getBpkTypeFromPvpAttribute(final IAuthProcessDataContainer session) { + 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 + // if (pvpbPKTypeAttr.startsWith(EAAFConstants.URN_PREFIX_CDID) && + // !pvpbPKTypeAttr.substring(EAAFConstants.URN_PREFIX_CDID.length(), + // EAAFConstants.URN_PREFIX_CDID.length() + 1).equals("+")) { + // log.warn("Receive uncorrect encoded bBKType attribute " + pvpbPKTypeAttr + " + // Starting + // attribute value correction ... "); + // pvpbPKTypeAttr = EAAFConstants.URN_PREFIX_CDID + "+" + + // pvpbPKTypeAttr.substring(EAAFConstants.URN_PREFIX_CDID.length() + 1); + // + // } + log.debug( + "Find PVP-Attr: " + PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME); + return pvpBpkTypeAttr; + } + + return null; + + /* + * INFO: This code could be used to extract the bPKType from + * 'PVPConstants.BPK_NAME', because the prefix of BPK_NAME attribute contains + * the postfix of the bPKType + * + * Now, all PVP Standardportals should be able to send + * 'EID_SECTOR_FOR_IDENTIFIER' PVP attributes + */ + // String pvpbPKValueAttr = + // session.getGenericDataFromSession(PVPConstants.BPK_NAME, + // String.class); + // String[] spitted = pvpbPKValueAttr.split(":"); + // if (MiscUtil.isEmpty(authData.getBPKType())) { + // Logger.debug("PVP assertion contains NO bPK/wbPK target attribute. " + + // "Starting target extraction from bPK/wbPK prefix ..."); + // //exract bPK/wbPK type from bpk attribute value prefix if type is + // //not transmitted as single attribute + // Pattern pattern = Pattern.compile("[a-zA-Z]{2}(-[a-zA-Z]+)?"); + // Matcher matcher = pattern.matcher(spitted[0]); + // if (matcher.matches()) { + // //find public service bPK + // authData.setBPKType(Constants.URN_PREFIX_CDID + "+" + spitted[0]); + // Logger.debug("Found bPK prefix. Set target to " + authData.getBPKType()); + // + // } else { + // //find business service wbPK + // authData.setBPKType(Constants.URN_PREFIX_WBPK+ "+" + spitted[0]); + // Logger.debug("Found wbPK prefix. Set target to " + authData.getBPKType()); + // + // } + // } + + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BPKBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BPKBuilder.java deleted file mode 100644 index 602546a2..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BPKBuilder.java +++ /dev/null @@ -1,302 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - ******************************************************************************/ -/* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ - - -package at.gv.egiz.eaaf.core.impl.idp.auth.builder; - -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.Base64Utils; - -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.exceptions.EAAFBuilderException; -import at.gv.egiz.eaaf.core.impl.data.Pair; - -/** - * Builder for the bPK, as defined in - * <code>"Ableitung f¨r die bereichsspezifische Personenkennzeichnung"</code> - * version <code>1.0.1</code> from <code>"reference.e-government.gv.at"</code>. - * - */ -public class BPKBuilder { - private static final Logger log = LoggerFactory.getLogger(BPKBuilder.class); - - /** - * Calculates an area specific unique person-identifier from a baseID - * - * @param baseID baseId from user but never null - * @param targetIdentifier target identifier for area specific identifier calculation but never null - * @return Pair consists of (unique person identifier for this target, targetArea) but never null - * @throws EAAFBuilderException if some input data are not valid - */ - public static Pair<String, String> generateAreaSpecificPersonIdentifier(String baseID, String targetIdentifier) throws EAAFBuilderException { - return generateAreaSpecificPersonIdentifier(baseID, EAAFConstants.URN_PREFIX_BASEID, targetIdentifier); - - } - - /** - * Calculates an area specific unique person-identifier from an unique identifier with a specific type - * - * @param baseID baseId from user but never null - * @param baseIdType Type of the baseID but never null - * @param targetIdentifier target identifier for area specific identifier calculation but never null - * @return Pair consists of (unique person identifier for this target, targetArea) but never null - * @throws EAAFBuilderException if some input data are not valid - */ - public static Pair<String, String> generateAreaSpecificPersonIdentifier(String baseID, String baseIdType, String targetIdentifier) throws EAAFBuilderException{ - if (StringUtils.isEmpty(baseID)) - throw new EAAFBuilderException("builder.00", new Object[]{"baseID is empty or null"}, - "BaseId is empty or null"); - - if (StringUtils.isEmpty(baseIdType)) - throw new EAAFBuilderException("builder.00", new Object[]{"the type of baseID is empty or null"}, - "Type of baseId is empty or null"); - - if (StringUtils.isEmpty(targetIdentifier)) - throw new EAAFBuilderException("builder.00", new Object[]{"SP specific target identifier is empty or null"}, - "SP specific target identifier is empty or null"); - - if (baseIdType.equals(EAAFConstants.URN_PREFIX_BASEID)) { - log.trace("Find baseID. Starting unique identifier caluclation for this target"); - - if (targetIdentifier.startsWith(EAAFConstants.URN_PREFIX_CDID) || - targetIdentifier.startsWith(EAAFConstants.URN_PREFIX_WBPK)) { - log.trace("Calculate bPK, wbPK, or STORK identifier for target: " + targetIdentifier); - return Pair.newInstance(calculatebPKwbPK(baseID + "+" + targetIdentifier), targetIdentifier); - - } else if (targetIdentifier.startsWith(EAAFConstants.URN_PREFIX_EIDAS)) { - log.trace("Calculate eIDAS identifier for target: " + targetIdentifier); - final String[] splittedTarget = targetIdentifier.split("\\+"); - final String cititzenCountryCode = splittedTarget[1]; - final String eIDASOutboundCountry = splittedTarget[2]; - - if (cititzenCountryCode.equalsIgnoreCase(eIDASOutboundCountry)) { - log.warn("Suspect configuration FOUND!!! CitizenCountry equals DestinationCountry"); - - } - return buildeIDASIdentifer(baseID, baseIdType, cititzenCountryCode, eIDASOutboundCountry); - - - } else - throw new EAAFBuilderException("builder.00", - new Object[]{"Target identifier: " + targetIdentifier + " is NOT allowed or unknown"}, - "Target identifier: " + targetIdentifier + " is NOT allowed or unknown"); - - } else { - log.trace("BaseID is not of type " + EAAFConstants.URN_PREFIX_BASEID + ". Check type against requested target ..."); - if (baseIdType.equals(targetIdentifier)) { - log.debug("Unique identifier is already area specific. Is nothing todo"); - return Pair.newInstance(baseID, targetIdentifier); - - } else { - log.warn("Get unique identifier for target: " + baseIdType + " but target: " + targetIdentifier + " is required!"); - throw new EAAFBuilderException("builder.00", - new Object[]{"Get unique identifier for target: " + baseIdType + " but target: " + targetIdentifier + " is required"}, - "Get unique identifier for target: " + baseIdType + " but target: " + targetIdentifier + " is required"); - - } - } - } - - - /** - * Builds the eIDAS from the given parameters. - * - * @param baseID baseID of the citizen - * @param baseIDType Type of the baseID - * @param sourceCountry CountryCode of that country, which build the eIDAs ID - * @param destinationCountry CountryCode of that country, which receives the eIDAs ID - * - * @return Pair<eIDAs, bPKType> in a BASE64 encoding - * @throws EAAFBuilderException if some input data are not valid - */ - private static Pair<String, String> buildeIDASIdentifer(String baseID, String baseIDType, String sourceCountry, String destinationCountry) - throws EAAFBuilderException { - String bPK = null; - String bPKType = null; - - // check if we have been called by public sector application - if (baseIDType.startsWith(EAAFConstants.URN_PREFIX_BASEID)) { - bPKType = EAAFConstants.URN_PREFIX_EIDAS + sourceCountry + "+" + destinationCountry; - log.debug("Building eIDAS identification from: [identValue]+" + bPKType); - bPK = calculatebPKwbPK(baseID + "+" + bPKType); - - } else { // if not, sector identification value is already calculated by BKU - log.debug("eIDAS eIdentifier already provided by BKU"); - bPK = baseID; - } - - if ((StringUtils.isEmpty(bPK) || - StringUtils.isEmpty(sourceCountry) || - StringUtils.isEmpty(destinationCountry))) { - throw new EAAFBuilderException("builder.00", - new Object[]{"eIDAS-ID", "Unvollständige Parameterangaben: identificationValue=" + - bPK + ", Zielland=" + destinationCountry + ", Ursprungsland=" + sourceCountry} - ,"eIDAS-ID: Unvollständige Parameterangaben: identificationValue=" + - bPK + ", Zielland=" + destinationCountry + ", Ursprungsland=" + sourceCountry); - } - - log.trace("eIDAS pseudonym generation finished. "); - final String eIdentifier = sourceCountry + "/" + destinationCountry + "/" + bPK; - - return Pair.newInstance(eIdentifier, bPKType); - } - - public static String encryptBPK(String bpk, String target, PublicKey publicKey) throws EAAFBuilderException { - final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - if (target.startsWith(EAAFConstants.URN_PREFIX_CDID)) - target = target.substring((EAAFConstants.URN_PREFIX_CDID).length()); - - final String input = "V1::urn:publicid:gv.at:cdid+" + target + "::" - + bpk + "::" - + sdf.format(new Date()); - //System.out.println(input); - byte[] result; - try { - final byte[] inputBytes = input.getBytes("ISO-8859-1"); - result = encrypt(inputBytes, publicKey); - return new String(Base64Utils.encode(result), "ISO-8859-1").replaceAll("\r\n", ""); - //return new String(Base64Utils.encode(result, "ISO-8859-1")).replaceAll("\r\n", ""); - - - } catch (final Exception e) { - throw new EAAFBuilderException("bPK encryption FAILED", null, - e.getMessage(), e); - - } - } - - public static String decryptBPK(String encryptedBpk, String target, PrivateKey privateKey) throws EAAFBuilderException { - String decryptedString; - try { - //byte[] encryptedBytes = Base64Utils.decode(encryptedBpk, false, "ISO-8859-1"); - final byte[] encryptedBytes = Base64Utils.decode(encryptedBpk.getBytes("ISO-8859-1")); - final byte[] decryptedBytes = decrypt(encryptedBytes, privateKey); - decryptedString = new String(decryptedBytes, "ISO-8859-1"); - - } catch (final Exception e) { - throw new EAAFBuilderException("bPK decryption FAILED", null, - e.getMessage(), e); - - } - - String tmp = decryptedString.substring(decryptedString.indexOf('+') + 1); - final String sector = tmp.substring(0, tmp.indexOf("::")); - tmp = tmp.substring(tmp.indexOf("::") + 2); - final String bPK = tmp.substring(0, tmp.indexOf("::")); - - if (target.startsWith(EAAFConstants.URN_PREFIX_CDID + "+")) - target = target.substring((EAAFConstants.URN_PREFIX_CDID + "+").length()); - - if (target.equals(sector)) - return bPK; - - else { - log.error("Decrypted bPK does not match to request bPK target."); - return null; - } - } - - private static String calculatebPKwbPK(String basisbegriff) throws EAAFBuilderException { - try { - final MessageDigest md = MessageDigest.getInstance("SHA-1"); - final byte[] hash = md.digest(basisbegriff.getBytes("ISO-8859-1")); - final String hashBase64 = new String(Base64Utils.encode(hash), "ISO-8859-1").replaceAll("\r\n", ""); //Base64Utils.encode(hash); - return hashBase64; - - } catch (final Exception ex) { - throw new EAAFBuilderException("builder.00", new Object[]{"bPK/wbPK", ex.toString()}, - ex.getMessage(), ex); - - } - - } - - private static byte[] encrypt(byte[] inputBytes, PublicKey publicKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { - byte[] result; - Cipher cipher = null; - try { - cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); // try with bouncycastle - - } catch(final NoSuchAlgorithmException e) { - cipher = Cipher.getInstance("RSA/ECB/OAEP"); // try with iaik provider - } - cipher.init(Cipher.ENCRYPT_MODE, publicKey); - result = cipher.doFinal(inputBytes); - - return result; - } - - private static byte[] decrypt(byte[] encryptedBytes, PrivateKey privateKey) - throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{ - byte[] result; - Cipher cipher = null; - try { - cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); // try with bouncycastle - - } catch(final NoSuchAlgorithmException e) { - cipher = Cipher.getInstance("RSA/ECB/OAEP"); // try with iaik provider - - } - cipher.init(Cipher.DECRYPT_MODE, privateKey); - result = cipher.doFinal(encryptedBytes); - return result; - - } -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilder.java new file mode 100644 index 00000000..a613bd56 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilder.java @@ -0,0 +1,317 @@ +/* + * Copyright 2014 Federal Chancellery Austria MOA-ID has been developed in a cooperation between + * BRZ, the Federal Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.auth.builder; + +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Base64Utils; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException; +import at.gv.egiz.eaaf.core.impl.data.Pair; + +/** + * Builder for the bPK, as defined in + * <code>"Ableitung f¨r die bereichsspezifische Personenkennzeichnung"</code> + * version <code>1.0.1</code> from + * <code>"reference.e-government.gv.at"</code>. + * + */ +public class BpkBuilder { + private static final Logger log = LoggerFactory.getLogger(BpkBuilder.class); + + /** + * Calculates an area specific unique person-identifier from a baseID. + * + * @param baseID baseId from user but never null + * @param targetIdentifier target identifier for area specific identifier + * calculation but never null + * @return Pair consists of (unique person identifier for this target, + * targetArea) but never null + * @throws EaafBuilderException if some input data are not valid + */ + public static Pair<String, String> generateAreaSpecificPersonIdentifier(final String baseID, + final String targetIdentifier) throws EaafBuilderException { + return generateAreaSpecificPersonIdentifier(baseID, EaafConstants.URN_PREFIX_BASEID, + targetIdentifier); + + } + + /** + * Calculates an area specific unique person-identifier from an unique + * identifier with a specific type. + * + * @param baseID baseId from user but never null + * @param baseIdType Type of the baseID but never null + * @param targetIdentifier target identifier for area specific identifier + * calculation but never null + * @return Pair consists of (unique person identifier for this target, + * targetArea) but never null + * @throws EaafBuilderException if some input data are not valid + */ + public static Pair<String, String> generateAreaSpecificPersonIdentifier(final String baseID, + final String baseIdType, final String targetIdentifier) throws EaafBuilderException { + if (StringUtils.isEmpty(baseID)) { + throw new EaafBuilderException("builder.00", new Object[] { "baseID is empty or null" }, + "BaseId is empty or null"); + } + + if (StringUtils.isEmpty(baseIdType)) { + throw new EaafBuilderException("builder.00", + new Object[] { "the type of baseID is empty or null" }, "Type of baseId is empty or null"); + } + + if (StringUtils.isEmpty(targetIdentifier)) { + throw new EaafBuilderException("builder.00", + new Object[] { "SP specific target identifier is empty or null" }, + "SP specific target identifier is empty or null"); + } + + if (baseIdType.equals(EaafConstants.URN_PREFIX_BASEID)) { + log.trace("Find baseID. Starting unique identifier caluclation for this target"); + + if (targetIdentifier.startsWith(EaafConstants.URN_PREFIX_CDID) + || targetIdentifier.startsWith(EaafConstants.URN_PREFIX_WBPK)) { + log.trace("Calculate bPK, wbPK, or STORK identifier for target: " + targetIdentifier); + return Pair.newInstance(calculatebPKwbPK(baseID + "+" + targetIdentifier), + targetIdentifier); + + } else if (targetIdentifier.startsWith(EaafConstants.URN_PREFIX_EIDAS)) { + log.trace("Calculate eIDAS identifier for target: " + targetIdentifier); + final String[] splittedTarget = targetIdentifier.split("\\+"); + final String cititzenCountryCode = splittedTarget[1]; + final String eidasOutboundCountry = splittedTarget[2]; + + if (cititzenCountryCode.equalsIgnoreCase(eidasOutboundCountry)) { + log.warn("Suspect configuration FOUND!!! CitizenCountry equals DestinationCountry"); + + } + return buildEidasIdentifer(baseID, baseIdType, cititzenCountryCode, eidasOutboundCountry); + + } else { + throw new EaafBuilderException("builder.00", + new Object[] { "Target identifier: " + targetIdentifier + " is NOT allowed or unknown" }, + "Target identifier: " + targetIdentifier + " is NOT allowed or unknown"); + } + + } else { + log.trace("BaseID is not of type " + EaafConstants.URN_PREFIX_BASEID + + ". Check type against requested target ..."); + if (baseIdType.equals(targetIdentifier)) { + log.debug("Unique identifier is already area specific. Is nothing todo"); + return Pair.newInstance(baseID, targetIdentifier); + + } else { + log.warn("Get unique identifier for target: " + baseIdType + " but target: " + + targetIdentifier + " is required!"); + throw new EaafBuilderException("builder.00", + new Object[] { "Get unique identifier for target: " + baseIdType + " but target: " + + targetIdentifier + " is required" }, + "Get unique identifier for target: " + baseIdType + " but target: " + targetIdentifier + + " is required"); + + } + } + } + + /** + * Builds the eIDAS from the given parameters. + * + * @param baseId baseID of the citizen + * @param baseIdType Type of the baseID + * @param sourceCountry CountryCode of that country, which build the eIDAs + * ID + * @param destinationCountry CountryCode of that country, which receives the + * eIDAs ID + * + * @return Pair eIDAs/bPKType in a BASE64 encoding + * @throws EaafBuilderException if some input data are not valid + */ + private static Pair<String, String> buildEidasIdentifer(final String baseId, + final String baseIdType, final String sourceCountry, final String destinationCountry) + throws EaafBuilderException { + String bpk = null; + String bpkType = null; + + // check if we have been called by public sector application + if (baseIdType.startsWith(EaafConstants.URN_PREFIX_BASEID)) { + bpkType = EaafConstants.URN_PREFIX_EIDAS + sourceCountry + "+" + destinationCountry; + log.debug("Building eIDAS identification from: [identValue]+" + bpkType); + bpk = calculatebPKwbPK(baseId + "+" + bpkType); + + } else { // if not, sector identification value is already calculated by BKU + log.debug("eIDAS eIdentifier already provided by BKU"); + bpk = baseId; + } + + if (StringUtils.isEmpty(bpk) || StringUtils.isEmpty(sourceCountry) + || StringUtils.isEmpty(destinationCountry)) { + throw new EaafBuilderException("builder.00", + new Object[] { "eIDAS-ID", + "Unvollständige Parameterangaben: identificationValue=" + bpk + ", Zielland=" + + destinationCountry + ", Ursprungsland=" + sourceCountry }, + "eIDAS-ID: Unvollständige Parameterangaben: identificationValue=" + bpk + ", Zielland=" + + destinationCountry + ", Ursprungsland=" + sourceCountry); + } + + log.trace("eIDAS pseudonym generation finished. "); + final String eIdentifier = sourceCountry + "/" + destinationCountry + "/" + bpk; + + return Pair.newInstance(eIdentifier, bpkType); + } + + /** + * Create an encrypted bPK. + * + * @param bpk unencrypted bPK + * @param target bPK target + * @param publicKey Public-Key used for encryption + * @return encrypted bPK + * @throws EaafBuilderException In case of an error + */ + public static String encryptBpk(final String bpk, String target, final PublicKey publicKey) + throws EaafBuilderException { + final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + if (target.startsWith(EaafConstants.URN_PREFIX_CDID)) { + target = target.substring(EaafConstants.URN_PREFIX_CDID.length()); + } + + final String input = + "V1::urn:publicid:gv.at:cdid+" + target + "::" + bpk + "::" + sdf.format(new Date()); + // System.out.println(input); + byte[] result; + try { + final byte[] inputBytes = input.getBytes("ISO-8859-1"); + result = encrypt(inputBytes, publicKey); + return new String(Base64Utils.encode(result), "ISO-8859-1").replaceAll("\r\n", ""); + // return new String(Base64Utils.encode(result, + // "ISO-8859-1")).replaceAll("\r\n", ""); + + } catch (final Exception e) { + throw new EaafBuilderException("bPK encryption FAILED", null, e.getMessage(), e); + + } + } + + /** + * Decrypt an encrypted bPK. + * + * @param encryptedBpk encrypted bPK + * @param target bPK target + * @param privateKey private-key for decryption + * @return bPK + * @throws EaafBuilderException In case of an error + */ + public static String decryptBpk(final String encryptedBpk, String target, + final PrivateKey privateKey) throws EaafBuilderException { + String decryptedString; + try { + // byte[] encryptedBytes = Base64Utils.decode(encryptedBpk, false, + // "ISO-8859-1"); + final byte[] encryptedBytes = Base64Utils.decode(encryptedBpk.getBytes("ISO-8859-1")); + final byte[] decryptedBytes = decrypt(encryptedBytes, privateKey); + decryptedString = new String(decryptedBytes, "ISO-8859-1"); + + } catch (final Exception e) { + throw new EaafBuilderException("bPK decryption FAILED", null, e.getMessage(), e); + + } + + String tmp = decryptedString.substring(decryptedString.indexOf('+') + 1); + final String sector = tmp.substring(0, tmp.indexOf("::")); + tmp = tmp.substring(tmp.indexOf("::") + 2); + final String bPK = tmp.substring(0, tmp.indexOf("::")); + + if (target.startsWith(EaafConstants.URN_PREFIX_CDID + "+")) { + target = target.substring((EaafConstants.URN_PREFIX_CDID + "+").length()); + } + + if (target.equals(sector)) { + return bPK; + } else { + log.error("Decrypted bPK does not match to request bPK target."); + return null; + } + } + + private static String calculatebPKwbPK(final String basisbegriff) throws EaafBuilderException { + try { + final MessageDigest md = MessageDigest.getInstance("SHA-1"); + final byte[] hash = md.digest(basisbegriff.getBytes("ISO-8859-1")); + final String hashBase64 = + new String(Base64Utils.encode(hash), "ISO-8859-1").replaceAll("\r\n", ""); // Base64Utils.encode(hash); + return hashBase64; + + } catch (final Exception ex) { + throw new EaafBuilderException("builder.00", new Object[] { "bPK/wbPK", ex.toString() }, + ex.getMessage(), ex); + + } + + } + + private static byte[] encrypt(final byte[] inputBytes, final PublicKey publicKey) + throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, + IllegalBlockSizeException, BadPaddingException { + byte[] result; + Cipher cipher = null; + try { + cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); // try with bouncycastle + + } catch (final NoSuchAlgorithmException e) { + cipher = Cipher.getInstance("RSA/ECB/OAEP"); // try with iaik provider + } + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + result = cipher.doFinal(inputBytes); + + return result; + } + + private static byte[] decrypt(final byte[] encryptedBytes, final PrivateKey privateKey) + throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, + IllegalBlockSizeException, BadPaddingException { + byte[] result; + Cipher cipher = null; + try { + cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); // try with bouncycastle + + } catch (final NoSuchAlgorithmException e) { + cipher = Cipher.getInstance("RSA/ECB/OAEP"); // try with iaik provider + + } + cipher.init(Cipher.DECRYPT_MODE, privateKey); + result = cipher.doFinal(encryptedBytes); + return result; + + } +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthProcessDataWrapper.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthProcessDataWrapper.java index e096b8e6..988a78b6 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthProcessDataWrapper.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/AuthProcessDataWrapper.java @@ -1,254 +1,337 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.auth.data; +import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.TimeZone; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.EaafAuthProcessDataConstants; +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.EaafStorageException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.idp.EAAFAuthProcessDataConstants; -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.EAAFStorageException; - -public class AuthProcessDataWrapper implements IAuthProcessDataContainer, EAAFAuthProcessDataConstants { - private static final Logger log = LoggerFactory.getLogger(AuthProcessDataWrapper.class); - - protected Map<String, Object> authProcessData; - - public AuthProcessDataWrapper(Map<String, Object> authProcessData) { - this.authProcessData = authProcessData; - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getIssueInstant() - */ - @Override - public String getIssueInstant() { - return wrapStringObject(VALUE_ISSUEINSTANT, null, String.class); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setIssueInstant(java.lang.String) - */ - @Override - public void setIssueInstant(String issueInstant) { - authProcessData.put(VALUE_ISSUEINSTANT, issueInstant); - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#isAuthenticated() - */ - @Override - public boolean isAuthenticated() { - return wrapStringObject(FLAG_IS_AUTHENTICATED, false, Boolean.class); - - } - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setAuthenticated(boolean) - */ - @Override - public void setAuthenticated(boolean authenticated) { - authProcessData.put(FLAG_IS_AUTHENTICATED, authenticated); - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getIdentityLink() - */ - @Override - public IIdentityLink getIdentityLink() { - return wrapStringObject(VALUE_IDENTITYLINK, null, IIdentityLink.class); - - } - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setIdentityLink(at.gv.egovernment.moa.id.auth.data.IdentityLink) - */ - @Override - public void setIdentityLink(IIdentityLink identityLink) { - authProcessData.put(VALUE_IDENTITYLINK, identityLink); - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#isMandateUsed() - */ - @Override - public boolean isMandateUsed() { - return wrapStringObject(FLAG_USE_MANDATE, false, Boolean.class); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setUseMandates(boolean) - */ - @Override - public void setUseMandates(boolean useMandates) { - authProcessData.put(FLAG_USE_MANDATE, useMandates); - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getQAALevel() - */ - @Override - public String getQAALevel() { - return wrapStringObject(VALUE_QAALEVEL, null, String.class); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setQAALevel(java.lang.String) - */ - @Override - public void setQAALevel(String qAALevel) { - authProcessData.put(VALUE_QAALEVEL, qAALevel); - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#isForeigner() - */ - @Override - public boolean isForeigner() { - return wrapStringObject(FLAG_IS_FOREIGNER, false, Boolean.class); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setForeigner(boolean) - */ - @Override - public void setForeigner(boolean isForeigner) { - authProcessData.put(FLAG_IS_FOREIGNER, isForeigner); - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#isOW() - */ - @Override - public boolean isOW() { - return wrapStringObject(FLAG_IS_ORGANWALTER, false, Boolean.class); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setOW(boolean) - */ - @Override - public void setOW(boolean isOW) { - authProcessData.put(FLAG_IS_ORGANWALTER, isOW); - - } - - @Override - public boolean isEIDProcess() { - return wrapStringObject(FLAG_IS_NEW_EID_PROCESS, false, Boolean.class); - } - - @Override - public void setEIDProcess(boolean value) { - authProcessData.put(FLAG_IS_NEW_EID_PROCESS, value); - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getSessionCreated() - */ - @Override - public Date getSessionCreated() { - return wrapStringObject(EAAFConstants.AUTH_DATA_CREATED, null, Date.class); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getGenericSessionDataStorage() - */ - @Override - public Map<String, Object> getGenericSessionDataStorage() { - final Map<String, Object> result = new HashMap<String, Object>(); - for (final String el : authProcessData.keySet()) { - if (el.startsWith(GENERIC_PREFIX)) - result.put(el.substring(GENERIC_PREFIX.length()), authProcessData.get(el)); - - } - - return result; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getGenericDataFromSession(java.lang.String) - */ - @Override - public Object getGenericDataFromSession(String key) { - return authProcessData.get(GENERIC_PREFIX + key); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getGenericDataFromSession(java.lang.String, java.lang.Class) - */ - @Override - public <T> T getGenericDataFromSession(String key, Class<T> clazz) { - return wrapStringObject(GENERIC_PREFIX + key, null, clazz); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setGenericDataToSession(java.lang.String, java.lang.Object) - */ - @Override - public void setGenericDataToSession(String key, Object object) throws EAAFStorageException { - authProcessData.put(GENERIC_PREFIX + key, object); - - } - - protected <T> T wrapStringObject(String key, Object defaultValue, Class<T> clazz) { - if (StringUtils.isNotEmpty(key)) { - final Object obj = authProcessData.get(key); - if (obj != null && clazz.isInstance(obj)) - return (T) obj; - } - - if (defaultValue == null) - return null; - - else if (clazz.isInstance(defaultValue)) - return (T)defaultValue; - - else { - log.error("DefaultValue: " + defaultValue.getClass().getName() + " is not of Type:" + clazz.getName()); - throw new IllegalStateException("DefaultValue: " + defaultValue.getClass().getName() + " is not of Type:" + clazz.getName()); - - } - } +public class AuthProcessDataWrapper + implements IAuthProcessDataContainer, EaafAuthProcessDataConstants { + private static final Logger log = LoggerFactory.getLogger(AuthProcessDataWrapper.class); + + protected Map<String, Object> authProcessData; + + public AuthProcessDataWrapper(final Map<String, Object> authProcessData) { + this.authProcessData = authProcessData; + + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getIssueInstant() + */ + @Override + public String getIssueInstant() { + return wrapStringObject(VALUE_ISSUEINSTANT, null, String.class); + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setIssueInstant( + * java.lang.String) + */ + @Override + public void setIssueInstant(final String issueInstant) { + authProcessData.put(VALUE_ISSUEINSTANT, issueInstant); + + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setIssueInstant( + * java.lang.String) + */ + @Override + public void setIssueInstant(final Date issueInstant) { + authProcessData.put(VALUE_ISSUEINSTANT, buildDateTimeUtc(issueInstant)); + + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#isAuthenticated() + */ + @Override + public boolean isAuthenticated() { + return wrapStringObject(FLAG_IS_AUTHENTICATED, false, Boolean.class); + + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setAuthenticated( + * boolean) + */ + @Override + public void setAuthenticated(final boolean authenticated) { + authProcessData.put(FLAG_IS_AUTHENTICATED, authenticated); + + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getIdentityLink() + */ + @Override + public IIdentityLink getIdentityLink() { + return wrapStringObject(VALUE_IDENTITYLINK, null, IIdentityLink.class); + + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setIdentityLink(at. + * gv.egovernment.moa .id.auth.data.IdentityLink) + */ + @Override + public void setIdentityLink(final IIdentityLink identityLink) { + authProcessData.put(VALUE_IDENTITYLINK, identityLink); + + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#isMandateUsed() + */ + @Override + public boolean isMandateUsed() { + return wrapStringObject(FLAG_USE_MANDATE, false, Boolean.class); + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setUseMandates( + * boolean) + */ + @Override + public void setUseMandates(final boolean useMandates) { + authProcessData.put(FLAG_USE_MANDATE, useMandates); + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getQAALevel() + */ + @Override + public String getQaaLevel() { + return wrapStringObject(VALUE_QAALEVEL, null, String.class); + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setQAALevel(java. + * lang.String) + */ + @Override + public void setQaaLevel(final String qaaLevel) { + authProcessData.put(VALUE_QAALEVEL, qaaLevel); + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#isForeigner() + */ + @Override + public boolean isForeigner() { + return wrapStringObject(FLAG_IS_FOREIGNER, false, Boolean.class); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setForeigner( + * boolean) + */ + @Override + public void setForeigner(final boolean isForeigner) { + authProcessData.put(FLAG_IS_FOREIGNER, isForeigner); + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#isOW() + */ + @Override + public boolean isOW() { + return wrapStringObject(FLAG_IS_ORGANWALTER, false, Boolean.class); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#setOW(boolean) + */ + @Override + public void setOW(final boolean isOW) { + authProcessData.put(FLAG_IS_ORGANWALTER, isOW); + + } + + @Override + public boolean isEidProcess() { + return wrapStringObject(FLAG_IS_NEW_EID_PROCESS, false, Boolean.class); + } + + @Override + public void setEidProcess(final boolean value) { + authProcessData.put(FLAG_IS_NEW_EID_PROCESS, value); + + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IAuthenticationSession#getSessionCreated() + */ + @Override + public Date getSessionCreated() { + return wrapStringObject(EaafConstants.AUTH_DATA_CREATED, null, Date.class); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession# + * getGenericSessionDataStorage() + */ + @Override + public Map<String, Object> getGenericSessionDataStorage() { + final Map<String, Object> result = new HashMap<>(); + for (final Map.Entry<String, Object> el : authProcessData.entrySet()) { + if (el.getKey().startsWith(GENERIC_PREFIX)) { + result.put(el.getKey().substring(GENERIC_PREFIX.length()), el.getValue()); + } + + } + + return result; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession# + * getGenericDataFromSession(java.lang. String) + */ + @Override + public Object getGenericDataFromSession(final String key) { + return authProcessData.get(GENERIC_PREFIX + key); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession# + * getGenericDataFromSession(java.lang. String, java.lang.Class) + */ + @Override + public <T> T getGenericDataFromSession(final String key, final Class<T> clazz) { + return wrapStringObject(GENERIC_PREFIX + key, null, clazz); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IAuthenticationSession# + * setGenericDataToSession(java.lang. String, java.lang.Object) + */ + @Override + public void setGenericDataToSession(final String key, final Object object) + throws EaafStorageException { + authProcessData.put(GENERIC_PREFIX + key, object); + + } + + protected <T> T wrapStringObject(final String key, final Object defaultValue, + final Class<T> clazz) { + if (StringUtils.isNotEmpty(key)) { + final Object obj = authProcessData.get(key); + if (obj != null && clazz.isInstance(obj)) { + return (T) obj; + } + } + + if (defaultValue == null) { + return null; + } else if (clazz.isInstance(defaultValue)) { + return (T) defaultValue; + } else { + log.error("DefaultValue: " + defaultValue.getClass().getName() + " is not of Type:" + + clazz.getName()); + throw new IllegalStateException("DefaultValue: " + defaultValue.getClass().getName() + + " is not of Type:" + clazz.getName()); + + } + } + + /** + * Builds a <code>dateTime</code> value in UTC from a <code>Calendar</code> value. + * + * @param date the <code>Calendar</code> value + * @return the <code>dateTime</code> value + */ + public static String buildDateTimeUtc(final Date date) { + + final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + f.setTimeZone(TimeZone.getTimeZone("UTC")); + + return f.format(date.getTime()); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/IdentityLink.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/IdentityLink.java index 367643ec..ee1037a1 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/IdentityLink.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/IdentityLink.java @@ -1,51 +1,25 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - ******************************************************************************/ /* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * Copyright 2014 Federal Chancellery Austria MOA-ID has been developed in a cooperation between + * BRZ, the Federal Chancellery Austria - ICT staff unit, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: http://www.osor.eu/eupl/ * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ package at.gv.egiz.eaaf.core.impl.idp.auth.data; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.Serializable; import java.security.PublicKey; @@ -55,252 +29,358 @@ import javax.xml.transform.TransformerException; import org.w3c.dom.Element; import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; -import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; - +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.core.impl.utils.XPathUtils; /** - * Data contained in an identity link issued by BMI, relevant to the MOA ID component. - * <br><code>"IdentityLink"</code> is the translation of <code>"Personenbindung"</code>. - * + * Data contained in an identity link issued by BMI, relevant to the MOA ID + * component. <br> + * <code>"IdentityLink"</code> is the translation of + * <code>"Personenbindung"</code>. + * * @author Paul Ivancsics * @version $Id$ */ -public class IdentityLink implements Serializable, IIdentityLink{ - - private static final long serialVersionUID = 1L; - - /** - * <code>"identificationValue"</code> is the translation of <code>"Stammzahl"</code>. - */ - private String identificationValue; - /** - * <code>"identificationType"</code> type of the identificationValue in the IdentityLink. - */ - private String identificationType; - /** - * first name - */ - private String givenName; - /** - * family name - */ - private String familyName; - - /** - * date of birth - */ - private String dateOfBirth; +public class IdentityLink implements Serializable, IIdentityLink { + + private static final long serialVersionUID = 1L; + + /** + * <code>"identificationValue"</code> is the translation of + * <code>"Stammzahl"</code>. + */ + private String identificationValue; + /** + * <code>"identificationType"</code> type of the identificationValue in the + * IdentityLink. + */ + private String identificationType; + /** + * first name. + */ + private String givenName; /** - * the original saml:Assertion-Element + * family name. */ - private Element samlAssertion; + private String familyName; + + /** + * date of birth. + */ + private String dateOfBirth; /** - * the serializes saml:Assertion + * the original saml:Assertion-Element. + */ + private transient Element samlAssertion; + /** + * the serializes saml:Assertion. */ private String serializedSamlAssertion; - /** - * Element /saml:Assertion/saml:AttributeStatement/saml:Subject/saml:SubjectConfirmation/saml:SubjectConfirmationData/pr:Person - */ - private Element prPerson; /** - * we need for each dsig:Reference Element all - * transformation elements + * Element + * /saml:Assertion/saml:AttributeStatement/saml:Subject + * /saml:SubjectConfirmation/saml:SubjectConfirmationData/pr:Person. */ - private Element[] dsigReferenceTransforms; - + private transient Element prPerson = null; + /** + * we need for each dsig:Reference Element all transformation elements. + */ + private transient Element[] dsigReferenceTransforms = null; + /** * The issuing time of the identity link SAML assertion. */ private String issueInstant; /** - * we need all public keys stored in - * the identity link + * we need all public keys stored in the identity link. */ private PublicKey[] publicKey; - /** - * Constructor for IdentityLink - */ - public IdentityLink() { - } + /** + * Constructor for IdentityLink. + */ + public IdentityLink() { + } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getDateOfBirth() - */ + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getDateOfBirth() + */ @Override -public String getDateOfBirth() { + public String getDateOfBirth() { return dateOfBirth; } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getFamilyName() - */ + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getFamilyName() + */ @Override -public String getFamilyName() { + public String getFamilyName() { return familyName; } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getGivenName() - */ + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getGivenName() + */ @Override -public String getGivenName() { + public String getGivenName() { return givenName; } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getName() - */ + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getName() + */ @Override @Deprecated public String getName() { return givenName + " " + familyName; - + } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getIdentificationValue() - */ + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#getIdentificationValue() + */ @Override -public String getIdentificationValue() { + public String getIdentificationValue() { return identificationValue; } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getIdentificationType() - */ - @Override - public String getIdentificationType() { - return identificationType; - } + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getIdentificationType() + */ + @Override + public String getIdentificationType() { + return identificationType; + } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setDateOfBirth(java.lang.String) - */ + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#setDateOfBirth(java.lang. + * String) + */ @Override -public void setDateOfBirth(String dateOfBirth) { + public void setDateOfBirth(final String dateOfBirth) { this.dateOfBirth = dateOfBirth; } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setFamilyName(java.lang.String) - */ + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#setFamilyName(java.lang. + * String) + */ @Override -public void setFamilyName(String familyName) { + public void setFamilyName(final String familyName) { this.familyName = familyName; } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setGivenName(java.lang.String) - */ + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setGivenName(java.lang. + * String) + */ @Override -public void setGivenName(String givenName) { + public void setGivenName(final String givenName) { this.givenName = givenName; } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setIdentificationValue(java.lang.String) - */ + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#setIdentificationValue(java. + * lang.String) + */ @Override -public void setIdentificationValue(String identificationValue) { + public void setIdentificationValue(final String identificationValue) { this.identificationValue = identificationValue; } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setIdentificationType(java.lang.String) - */ - @Override - public void setIdentificationType(String identificationType) { - this.identificationType = identificationType; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getSamlAssertion() - */ + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#setIdentificationType(java. + * lang.String) + */ @Override -public Element getSamlAssertion() { - return samlAssertion; + public void setIdentificationType(final String identificationType) { + this.identificationType = identificationType; } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getSerializedSamlAssertion() - */ + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getSamlAssertion() + */ + @Override + public Element getSamlAssertion() { + if (this.samlAssertion == null) { + try { + this.samlAssertion = DomUtils.parseXmlNonValidating( + new ByteArrayInputStream(serializedSamlAssertion.getBytes("UTF-8"))); + + } catch (final Exception e) { + throw new RuntimeException(e); + + } + } + + return this.samlAssertion; + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#getSerializedSamlAssertion() + */ @Override -public String getSerializedSamlAssertion() { + public String getSerializedSamlAssertion() { return serializedSamlAssertion; } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setSamlAssertion(org.w3c.dom.Element) - */ + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#setSamlAssertion(org.w3c.dom + * .Element) + */ @Override -public void setSamlAssertion(Element samlAssertion) throws TransformerException, IOException { + public void setSamlAssertion(final Element samlAssertion) + throws TransformerException, IOException { this.samlAssertion = samlAssertion; - this.serializedSamlAssertion = DOMUtils.serializeNode(samlAssertion); + this.serializedSamlAssertion = DomUtils.serializeNode(samlAssertion); } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getDsigReferenceTransforms() - */ + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#getDsigReferenceTransforms() + */ @Override -public Element[] getDsigReferenceTransforms() { - return dsigReferenceTransforms; + public Element[] getDsigReferenceTransforms() { + if (dsigReferenceTransforms != null) { + return dsigReferenceTransforms.clone(); + + } else { + return null; + + } } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setDsigReferenceTransforms(org.w3c.dom.Element[]) - */ + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#setDsigReferenceTransforms( + * org.w3c.dom.Element []) + */ @Override -public void setDsigReferenceTransforms(Element[] dsigReferenceTransforms) { - this.dsigReferenceTransforms = dsigReferenceTransforms; + public void setDsigReferenceTransforms(final Element[] dsigReferenceTransforms) { + if (dsigReferenceTransforms != null) { + this.dsigReferenceTransforms = dsigReferenceTransforms.clone(); + + } } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getPublicKey() - */ + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getPublicKey() + */ @Override -public PublicKey[] getPublicKey() { - return publicKey; + public PublicKey[] getPublicKey() { + if (publicKey != null) { + return publicKey.clone(); + + } else { + return null; + + } } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setPublicKey(java.security.PublicKey[]) - */ + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#setPublicKey(java.security. + * PublicKey[]) + */ @Override -public void setPublicKey(PublicKey[] publicKey) { - this.publicKey = publicKey; + public void setPublicKey(final PublicKey[] publicKey) { + if (publicKey != null) { + this.publicKey = publicKey.clone(); + + } } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getPrPerson() - */ + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getPrPerson() + */ @Override -public Element getPrPerson() { + public Element getPrPerson() { + if (prPerson == null) { + prPerson = (Element) XPathUtils.selectSingleNode( + getSamlAssertion(), SimpleIdentityLinkAssertionParser.PERSON_XPATH); + + } + return prPerson; } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setPrPerson(org.w3c.dom.Element) - */ + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#setPrPerson(org.w3c.dom. + * Element) + */ @Override -public void setPrPerson(Element prPerson) { + public void setPrPerson(final Element prPerson) { this.prPerson = prPerson; } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getIssueInstant() - */ + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#getIssueInstant() + */ @Override -public String getIssueInstant() { + public String getIssueInstant() { return issueInstant; } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IIdentityLink#setIssueInstant(java.lang.String) - */ + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.data.IIdentityLink#setIssueInstant(java.lang. + * String) + */ @Override -public void setIssueInstant(String issueInstant) { + public void setIssueInstant(final String issueInstant) { this.issueInstant = issueInstant; } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/SimpleIdentityLinkAssertionParser.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/SimpleIdentityLinkAssertionParser.java index 658e6a42..acb877c2 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/SimpleIdentityLinkAssertionParser.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/data/SimpleIdentityLinkAssertionParser.java @@ -1,47 +1,20 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - ******************************************************************************/ /* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * Copyright 2014 Federal Chancellery Austria MOA-ID has been developed in a cooperation between + * BRZ, the Federal Chancellery Austria - ICT staff unit, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: http://www.osor.eu/eupl/ * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ package at.gv.egiz.eaaf.core.impl.idp.auth.data; @@ -55,17 +28,16 @@ import org.springframework.util.Base64Utils; import org.w3c.dom.Element; import org.w3c.dom.traversal.NodeIterator; -import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants; +import at.gv.egiz.eaaf.core.api.data.XmlNamespaceConstants; import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; -import at.gv.egiz.eaaf.core.exceptions.EAAFParserException; -import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; +import at.gv.egiz.eaaf.core.exceptions.EaafParserException; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; import at.gv.egiz.eaaf.core.impl.utils.XPathUtils; /** - * Parses MDS from an identity link <code><saml:Assertion></code> - * <br> + * Parses MDS from an identity link. <code><saml:Assertion></code> <br> * <b>This IDL parser extract NO key information!</b> - + * */ public class SimpleIdentityLinkAssertionParser { @@ -73,252 +45,172 @@ public class SimpleIdentityLinkAssertionParser { // XPath namespace prefix shortcuts // - /** Xpath prefix for reaching PersonData Namespaces */ - private static final String PDATA = XMLNamespaceConstants.PD_PREFIX + ":"; - /** Xpath prefix for reaching SAML Namespaces */ - private static final String SAML = XMLNamespaceConstants.SAML_PREFIX + ":"; - /** Xpath prefix for reaching XML-DSIG Namespaces */ - private static final String DSIG = XMLNamespaceConstants.DSIG_PREFIX + ":"; - /** Xpath prefix for reaching ECDS Namespaces */ - private static final String ECDSA = XMLNamespaceConstants.ECDSA_PREFIX + ":"; - /** Xpath expression to the root element */ - private static final String ROOT = ""; - /** Xpath expression to the SAMLSubjectConfirmationData element */ + /** Xpath prefix for reaching PersonData Namespaces. */ + private static final String PDATA = XmlNamespaceConstants.PD_PREFIX + ":"; + /** Xpath prefix for reaching SAML Namespaces. */ + private static final String SAML = XmlNamespaceConstants.SAML_PREFIX + ":"; + /** Xpath prefix for reaching XML-DSIG Namespaces. */ + private static final String DSIG = XmlNamespaceConstants.DSIG_PREFIX + ":"; + /** Xpath expression to the root element. */ + private static final String ROOT = ""; + /** Xpath expression to the SAMLSubjectConfirmationData element. */ private static final String SAML_SUBJECT_CONFIRMATION_DATA_XPATH = - ROOT - + SAML - + "AttributeStatement/" - + SAML - + "Subject/" - + SAML - + "SubjectConfirmation/" - + SAML - + "SubjectConfirmationData"; - /** Xpath expression to the PersonData element */ - private static final String PERSON_XPATH = - SAML_SUBJECT_CONFIRMATION_DATA_XPATH - + "/" - + PDATA - + "Person"; - /** Xpath expression to the PersonData GivenName element */ + ROOT + SAML + "AttributeStatement/" + SAML + "Subject/" + SAML + "SubjectConfirmation/" + SAML + + "SubjectConfirmationData"; + /** Xpath expression to the PersonData element. */ + public static final String PERSON_XPATH = + SAML_SUBJECT_CONFIRMATION_DATA_XPATH + "/" + PDATA + "Person"; + /** Xpath expression to the PersonData GivenName element. */ public static final String PERSON_GIVEN_NAME_XPATH = - PERSON_XPATH - + "/" - + PDATA - + "Name/" - + PDATA - + "GivenName"; - /** Xpath expression to the PersonData FamilyName element */ + PERSON_XPATH + "/" + PDATA + "Name/" + PDATA + "GivenName"; + /** Xpath expression to the PersonData FamilyName element. */ public static final String PERSON_FAMILY_NAME_XPATH = - PERSON_XPATH - + "/" - + PDATA - + "Name/" - + PDATA - + "FamilyName"; - /** Xpath expression to the PersonData DateOfBirth element */ + PERSON_XPATH + "/" + PDATA + "Name/" + PDATA + "FamilyName"; + /** Xpath expression to the PersonData DateOfBirth element. */ public static final String PERSON_DATE_OF_BIRTH_XPATH = - PERSON_XPATH - + "/" - + PDATA - + "DateOfBirth"; - /** Xpath expression to the Identification element */ - private static final String PERSON_IDENT_XPATH = - PERSON_XPATH - + "/" - + PDATA - + "Identification"; - - /** Xpath expression to the Identification Value element */ + PERSON_XPATH + "/" + PDATA + "DateOfBirth"; + /** Xpath expression to the Identification Value element. */ public static final String PERSON_IDENT_VALUE_XPATH = - PERSON_XPATH - + "/" - + PDATA - + "Identification/" - + PDATA - + "Value"; + PERSON_XPATH + "/" + PDATA + "Identification/" + PDATA + "Value"; + + /** Xpath expression to the Identification Value element. */ + public static final String PERSON_IDENT_TYPE_XPATH = + PERSON_XPATH + "/" + PDATA + "Identification/" + PDATA + "Type"; - /** Xpath expression to the Identification Value element */ - public static final String PERSON_IDENT_TYPE_XPATH = - PERSON_XPATH - + "/" - + PDATA - + "Identification/" - + PDATA - + "Type"; + /** Xpath expression to the DSIG X509Certificate element. */ + private static final String DSIG_CERTIFICATES_XPATH = ROOT + DSIG + "Signature/" + DSIG + + "KeyInfo/" + DSIG + "X509Data/" + DSIG + "X509Certificate"; + /** Xpath expression to the DSIG Transforms element. */ + private static final String DSIG_REFERENCE_TRANSFORMATION_XPATH = + ROOT + DSIG + "Signature/" + DSIG + "SignedInfo/" + DSIG + "Reference/" + DSIG + "Transforms"; - /** Xpath expression to the RSAKeyValue element */ - private static final String RSA_KEY_VALUE_XPATH = - ROOT - + SAML - + "AttributeStatement/" - + SAML - + "Attribute/" - + SAML - + "AttributeValue/" - + DSIG - + "RSAKeyValue"; + /** The IssueInstant attribute of the SAML assertion. */ + private static final String ISSUE_INSTANT_ATTR = "IssueInstant"; - /** Xpath expression to the ECKeyValue element */ - private static final String ECDSA_KEY_VALUE_XPATH = - ROOT - + SAML - + "AttributeStatement/" - + SAML - + "Attribute/" - + SAML - + "AttributeValue/" - + ECDSA - + "ECDSAKeyValue"; + public static final String ASSERTIONID = "AssertionID"; - - /** Xpath expression to the RSA Modulus element */ - private static final String RSA_KEY_MODULUS_XPATH = DSIG + "Modulus"; - /** Xpath expression to the RSA Exponent element */ - private static final String RSA_KEY_EXPONENT_XPATH = DSIG + "Exponent"; - /** Xpath expression to the DSIG X509Certificate element */ - private static final String DSIG_CERTIFICATES_XPATH = - ROOT - + DSIG - + "Signature/" - + DSIG - + "KeyInfo/" - + DSIG - + "X509Data/" - + DSIG - + "X509Certificate"; - /** Xpath expression to the DSIG Transforms element */ - private static final String DSIG_REFERENCE_TRANSFORMATION_XPATH = - ROOT - + DSIG - + "Signature/" - + DSIG - + "SignedInfo/" - + DSIG - + "Reference/" - + DSIG - + "Transforms"; - - /** The IssueInstant attribute of the SAML assertion */ - private static final String ISSUE_INSTANT_ATTR = "IssueInstant"; - - public static final String ASSERTIONID = "AssertionID"; - - /**This is the root element of the XML-Document provided by the Security Layer Card*/ + /** + * This is the root element of the XML-Document provided by the Security Layer + * Card. + */ private Element assertionElem; /** - * Constructor for <code>IdentityLinkAssertionParser</code>. - * A DOM-representation of the incoming String will be created + * Constructor for <code>IdentityLinkAssertionParser</code>. A + * DOM-representation of the incoming String will be created + * * @param xmlAssertion <code><saml:Assertion></code> as String - * @throws EAAFParserException on any parsing error + * @throws EaafParserException on any parsing error */ - public SimpleIdentityLinkAssertionParser(String xmlAssertion) throws EAAFParserException { + public SimpleIdentityLinkAssertionParser(final String xmlAssertion) throws EaafParserException { try { - InputStream s = new ByteArrayInputStream(xmlAssertion.getBytes("UTF-8")); - assertionElem = DOMUtils.parseXmlValidating(s); - - } - catch (Throwable t) { - throw new EAAFParserException("parser.01", new Object[] { t.toString()}, t); - + final InputStream s = new ByteArrayInputStream(xmlAssertion.getBytes("UTF-8")); + assertionElem = DomUtils.parseXmlValidating(s); + + } catch (final Throwable t) { + throw new EaafParserException("parser.01", new Object[] { t.toString() }, t); + } } - + /** * Sets the <@link assertionElem>. + * * @param xmlAssertion the assertion element - * @throws EAAFParserException on any parsing error + * @throws EaafParserException on any parsing error */ - public SimpleIdentityLinkAssertionParser(Element xmlAssertion) throws EAAFParserException { + public SimpleIdentityLinkAssertionParser(final Element xmlAssertion) throws EaafParserException { assertionElem = xmlAssertion; } /** - * Constructor for <code>IdentityLinkAssertionParser</code>. - * A DOM-representation of the incoming Inputstream will be created + * Constructor for <code>IdentityLinkAssertionParser</code>. A + * DOM-representation of the incoming Inputstream will be created + * * @param xmlAssertion <code><saml:Assertion></code> as InputStream - * @throws EAAFParserException on any parsing error + * @throws EaafParserException on any parsing error */ - public SimpleIdentityLinkAssertionParser(InputStream xmlAssertion) throws EAAFParserException { + public SimpleIdentityLinkAssertionParser(final InputStream xmlAssertion) + throws EaafParserException { try { - assertionElem = DOMUtils.parseXmlValidating(xmlAssertion); - - } - catch (Throwable t) { - throw new EAAFParserException("parser.01", new Object[] { t.toString() }, t); - + assertionElem = DomUtils.parseXmlValidating(xmlAssertion); + + } catch (final Throwable t) { + throw new EaafParserException("parser.01", new Object[] { t.toString() }, t); + } } /** - * Parses the identity link from the <code><saml:Assertion></code> + * Parses the identity link from the <code><saml:Assertion></code>. + * * @return Identity link - * @throws EAAFParserException on any parsing error + * @throws EaafParserException on any parsing error */ - public IIdentityLink parseIdentityLink() throws EAAFParserException { + public IIdentityLink parseIdentityLink() throws EaafParserException { IIdentityLink identityLink; try { identityLink = new IdentityLink(); identityLink.setSamlAssertion(assertionElem); identityLink.setIssueInstant(assertionElem.getAttribute(ISSUE_INSTANT_ATTR)); - identityLink.setPrPerson((Element) - XPathUtils.selectSingleNode(assertionElem, PERSON_XPATH)); + identityLink.setPrPerson((Element) XPathUtils.selectSingleNode(assertionElem, PERSON_XPATH)); identityLink.setIdentificationValue( - XPathUtils.getElementValue(assertionElem, PERSON_IDENT_VALUE_XPATH, "")); - identityLink.setIdentificationType( - XPathUtils.getElementValue(assertionElem, PERSON_IDENT_TYPE_XPATH, "")); - - String givenname = XPathUtils.getElementValue(assertionElem, PERSON_GIVEN_NAME_XPATH, ""); - String familyname = XPathUtils.getElementValue(assertionElem, PERSON_FAMILY_NAME_XPATH, ""); + XPathUtils.getElementValue(assertionElem, PERSON_IDENT_VALUE_XPATH, "")); + identityLink.setIdentificationType( + XPathUtils.getElementValue(assertionElem, PERSON_IDENT_TYPE_XPATH, "")); + + final String givenname = + XPathUtils.getElementValue(assertionElem, PERSON_GIVEN_NAME_XPATH, ""); + final String familyname = + XPathUtils.getElementValue(assertionElem, PERSON_FAMILY_NAME_XPATH, ""); + + // replace ' in name with ' + // givenname = givenname.replaceAll("'", "'"); + // familyname = familyname.replaceAll("'", "'"); - // replace ' in name with ' -// givenname = givenname.replaceAll("'", "'"); -// familyname = familyname.replaceAll("'", "'"); - identityLink.setGivenName(givenname); identityLink.setFamilyName(familyname); identityLink.setDateOfBirth( - XPathUtils.getElementValue(assertionElem, PERSON_DATE_OF_BIRTH_XPATH, "")); - NodeIterator dsigRefTransforms = - XPathUtils.selectNodeIterator(assertionElem, DSIG_REFERENCE_TRANSFORMATION_XPATH); - List transElems = new ArrayList(); - Element transformsElem; - while ((transformsElem = (Element) dsigRefTransforms.nextNode()) != null) { - transElems.add(transformsElem); - } - Element[] result = new Element[transElems.size()]; - transElems.toArray(result); - identityLink.setDsigReferenceTransforms(result); - - //identityLink.setPublicKey(getPublicKeys()); - - } - catch (Throwable t) { - throw new EAAFParserException("parser.01", new Object[] { t.toString() }, t); + XPathUtils.getElementValue(assertionElem, PERSON_DATE_OF_BIRTH_XPATH, "")); + final NodeIterator dsigRefTransforms = + XPathUtils.selectNodeIterator(assertionElem, DSIG_REFERENCE_TRANSFORMATION_XPATH); + final List transElems = new ArrayList(); + Element transformsElem; + while ((transformsElem = (Element) dsigRefTransforms.nextNode()) != null) { + transElems.add(transformsElem); + } + final Element[] result = new Element[transElems.size()]; + transElems.toArray(result); + identityLink.setDsigReferenceTransforms(result); + + // identityLink.setPublicKey(getPublicKeys()); + + } catch (final Throwable t) { + throw new EaafParserException("parser.01", new Object[] { t.toString() }, t); } return identityLink; } /** - * Parses a string array of decoded base64 certificates from - * the <code><InfoboxReadResponse></code> found in the dsig-signature - * @return String[] with raw-certificates from the dsig-signature keyinfo - * @throws Exception - */ + * Parses a string array of decoded base64 certificates from the + * <code><InfoboxReadResponse></code> found in the dsig-signature. + * + * @return String[] with raw-certificates from the dsig-signature keyinfo + * @throws Exception In case of an error + */ public String[] getCertificates() throws Exception { - List certs = new ArrayList(); - NodeIterator rsaIter = - XPathUtils.selectNodeIterator(assertionElem, DSIG_CERTIFICATES_XPATH); + final List certs = new ArrayList(); + final NodeIterator rsaIter = + XPathUtils.selectNodeIterator(assertionElem, DSIG_CERTIFICATES_XPATH); Element certElem; while ((certElem = (Element) rsaIter.nextNode()) != null) { - String content = DOMUtils.getText(certElem); - certs.add(new String(Base64Utils.decodeFromString(content))); - + final String content = DomUtils.getText(certElem); + certs.add(new String(Base64Utils.decodeFromString(content), "UTF-8")); + } - String[] result = new String[certs.size()]; + final String[] result = new String[certs.size()]; certs.toArray(result); return result; diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java index ce9ba57c..3d093a9f 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.auth.modules; import java.io.ByteArrayOutputStream; @@ -51,221 +44,228 @@ import org.springframework.core.io.ResourceLoader; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IRequestStorage; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController; import at.gv.egiz.eaaf.core.impl.idp.process.springweb.AbstractTask; -import at.gv.egiz.eaaf.core.impl.utils.DataURLBuilder; +import at.gv.egiz.eaaf.core.impl.utils.DataUrlBuilder; /** - * Task based counterpart to {@link AuthServlet}, providing the same utility methods (error handling, parameter parsing - * etc.).</p> The code has been taken from {@link AuthServlet}. + * Task based counterpart to {@link AuthServlet}, providing the same utility + * methods (error handling, parameter parsing etc.). + * </p> + * The code has been taken from {@link AuthServlet}. */ public abstract class AbstractAuthServletTask extends AbstractTask { - private static final Logger log = LoggerFactory.getLogger(AbstractAuthServletTask.class); - - @Autowired(required=true) IProtocolAuthenticationService protAuchService; - @Autowired(required=true) protected IRequestStorage requestStoreage; - @Autowired(required=true) protected IConfiguration authConfig; - @Autowired(required=true) protected ResourceLoader resourceLoader; - - @Autowired protected IRevisionLogger revisionsLogger; - - protected static final String ERROR_CODE_PARAM = "errorid"; - - protected IRequest pendingReq = null; - - @Override - public abstract void execute(ExecutionContext executionContext, HttpServletRequest request, - HttpServletResponse response) throws TaskExecutionException; - - - @Override - protected final IRequest internalExecute(IRequest pendingReq, ExecutionContext executionContext, HttpServletRequest request, - HttpServletResponse response) throws TaskExecutionException { - //set pending-request object - this.pendingReq = pendingReq; - - //add latest pendingRequestId on execution context - executionContext.put(EAAFConstants.PROCESS_ENGINE_PENDINGREQUESTID, pendingReq.getPendingRequestId()); - - //execute task specific action - execute(executionContext, request, response); - - //return pending-request object - return this.pendingReq; - } - - /** - * Redirect the authentication process to protocol specific finalization endpoint. - * @param executionContext - * - * @param pendingReq Actually processed protocol specific authentication request - * @param httpResp - * @throws IOException - * @throws EAAFException - */ - protected void performRedirectToProtocolFinialization(ExecutionContext executionContext, IRequest pendingReq, HttpServletRequest httpReq, HttpServletResponse httpResp) throws EAAFException, IOException { - final Object frontChannelRedirectFlagObj = executionContext.get(EAAFConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT); - if (frontChannelRedirectFlagObj != null && frontChannelRedirectFlagObj instanceof Boolean && - (Boolean)frontChannelRedirectFlagObj) { - log.info("AuthProcess finished. Forward to Protocol finalization."); - protAuchService.finalizeAuthentication(httpReq, httpResp, pendingReq); - - } else { - log.info("AuthProcess finished. Redirect to Protocol Dispatcher."); - requestStoreage.storePendingRequest(pendingReq); - performRedirectToItself(pendingReq, httpResp, ProtocolFinalizationController.ENDPOINT_FINALIZEPROTOCOL); - - } - - - - } - - /** - * Redirect the authentication process to IDP itself - * - * @param pendingReq Actually processed protocol specific authentication request - * @param httpResp - * @param idpEndPoint Servlet EndPoint that should receive the redirect - */ - protected void performRedirectToItself(IRequest pendingReq, HttpServletResponse httpResp, String idpEndPoint) { - final String redirectURL = new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), - idpEndPoint, pendingReq.getPendingRequestId()); - - httpResp.setContentType("text/html"); - httpResp.setStatus(302); - httpResp.addHeader("Location", redirectURL); - log.debug("REDIRECT TO: " + redirectURL); - - } - - - /** - * Parses the request input stream for parameters, assuming parameters are - * encoded UTF-8 (no standard exists how browsers should encode them). - * - * @param req - * servlet request - * - * @return mapping parameter name -> value - * - * @throws IOException - * if parsing request parameters fails. - * - * @throws FileUploadException - * if parsing request parameters fails. - */ - protected Map<String, String> getParameters(HttpServletRequest req) throws IOException, - FileUploadException { - - final Map<String, String> parameters = new HashMap<String, String>(); - - if (ServletFileUpload.isMultipartContent(req)) { - // request is encoded as mulitpart/form-data - final FileItemFactory factory = new DiskFileItemFactory(); - ServletFileUpload upload = null; - upload = new ServletFileUpload(factory); - List items = null; - items = upload.parseRequest(req); - for (int i = 0; i < items.size(); i++) { - final FileItem item = (FileItem) items.get(i); - if (item.isFormField()) { - // Process only form fields - no file upload items - parameters.put(item.getFieldName(), item.getString("UTF-8")); - - //log requests on trace - if (log.isTraceEnabled()) { - final String logString = item.getString("UTF-8"); - - // TODO use RegExp - final String startS = "<pr:Identification><pr:Value>"; - final String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>"; - String logWithMaskedBaseid = logString; - final int start = logString.indexOf(startS); - if (start > -1) { - final int end = logString.indexOf(endS); - if (end > -1) { - logWithMaskedBaseid = logString.substring(0, start); - logWithMaskedBaseid += startS; - logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx"; - logWithMaskedBaseid += logString.substring(end, - logString.length()); - } - } - - log.debug("Processed multipart/form-data request parameter: \nName: " - + item.getFieldName() - + "\nValue: " - + logWithMaskedBaseid); - } - - } - } - } - - else { - final Iterator<Entry<String, String[]>> requestParamIt = req.getParameterMap().entrySet().iterator(); - while (requestParamIt.hasNext()) { - final Entry<String, String[]> entry = requestParamIt.next(); - final String key = entry.getKey(); - final String[] values = entry.getValue(); - // take the last value from the value array since the legacy code above also does it this way - parameters.put(key, ArrayUtils.isEmpty(values) ? null : values[values.length-1]); - } - - } - - return parameters; - } - - /** - * Reads bytes up to a delimiter, consuming the delimiter. - * - * @param in - * input stream - * @param delimiter - * delimiter character - * @return String constructed from the read bytes - * @throws IOException - */ - protected String readBytesUpTo(InputStream in, char delimiter) - throws IOException { - final ByteArrayOutputStream bout = new ByteArrayOutputStream(); - boolean done = false; - int b; - while (!done && (b = in.read()) >= 0) { - if (b == delimiter) - done = true; - else - bout.write(b); - } - return bout.toString(); - } - - /** - * Adds a parameter to a URL. - * - * @param url - * the URL - * @param paramname - * parameter name - * @param paramvalue - * parameter value - * @return the URL with parameter added - */ - protected static String addURLParameter(String url, String paramname, - String paramvalue) { - final String param = paramname + "=" + paramvalue; - if (url.indexOf("?") < 0) - return url + "?" + param; - else - return url + "&" + param; - } + private static final Logger log = LoggerFactory.getLogger(AbstractAuthServletTask.class); + + @Autowired(required = true) + IProtocolAuthenticationService protAuchService; + @Autowired(required = true) + protected IRequestStorage requestStoreage; + @Autowired(required = true) + protected IConfiguration authConfig; + @Autowired(required = true) + protected ResourceLoader resourceLoader; + + @Autowired + protected IRevisionLogger revisionsLogger; + + protected static final String ERROR_CODE_PARAM = "errorid"; + + protected IRequest pendingReq = null; + + @Override + public abstract void execute(ExecutionContext executionContext, HttpServletRequest request, + HttpServletResponse response) throws TaskExecutionException; + + @Override + protected final IRequest internalExecute(final IRequest pendingReq, + final ExecutionContext executionContext, final HttpServletRequest request, + final HttpServletResponse response) throws TaskExecutionException { + // set pending-request object + this.pendingReq = pendingReq; + + // add latest pendingRequestId on execution context + executionContext.put(EaafConstants.PROCESS_ENGINE_PENDINGREQUESTID, + pendingReq.getPendingRequestId()); + + // execute task specific action + execute(executionContext, request, response); + + // return pending-request object + return this.pendingReq; + } + + /** + * Redirect the authentication process to protocol specific finalization + * endpoint. + * + * @param executionContext + * + * @param pendingReq Actually processed protocol specific authentication + * request + * @param httpResp http response object + * @throws IOException In case of a general error + * @throws EaafException In case of an application error + */ + protected void performRedirectToProtocolFinialization(final ExecutionContext executionContext, + final IRequest pendingReq, final HttpServletRequest httpReq, + final HttpServletResponse httpResp) throws EaafException, IOException { + final Object frontChannelRedirectFlagObj = + executionContext.get(EaafConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT); + if (frontChannelRedirectFlagObj != null && frontChannelRedirectFlagObj instanceof Boolean + && (Boolean) frontChannelRedirectFlagObj) { + log.info("AuthProcess finished. Forward to Protocol finalization."); + protAuchService.finalizeAuthentication(httpReq, httpResp, pendingReq); + + } else { + log.info("AuthProcess finished. Redirect to Protocol Dispatcher."); + requestStoreage.storePendingRequest(pendingReq); + performRedirectToItself(pendingReq, httpResp, + ProtocolFinalizationController.ENDPOINT_FINALIZEPROTOCOL); + + } + + } + + /** + * Redirect the authentication process to IDP itself. + * + * @param pendingReq Actually processed protocol specific authentication + * request + * @param httpResp http response + * @param idpEndPoint Servlet EndPoint that should receive the redirect + */ + protected void performRedirectToItself(final IRequest pendingReq, + final HttpServletResponse httpResp, final String idpEndPoint) { + final String redirectUrl = new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), + idpEndPoint, pendingReq.getPendingRequestId()); + + httpResp.setContentType("text/html"); + httpResp.setStatus(302); + httpResp.addHeader("Location", redirectUrl); + log.debug("REDIRECT TO: " + redirectUrl); + + } + + /** + * Parses the request input stream for parameters, assuming parameters are + * encoded UTF-8 (no standard exists how browsers should encode them). + * + * @param req servlet request + * + * @return mapping parameter name -> value + * + * @throws IOException if parsing request parameters fails. + * + * @throws FileUploadException if parsing request parameters fails. + */ + protected Map<String, String> getParameters(final HttpServletRequest req) + throws IOException, FileUploadException { + + final Map<String, String> parameters = new HashMap<>(); + + if (ServletFileUpload.isMultipartContent(req)) { + // request is encoded as mulitpart/form-data + final FileItemFactory factory = new DiskFileItemFactory(); + ServletFileUpload upload = null; + upload = new ServletFileUpload(factory); + List items = null; + items = upload.parseRequest(req); + for (int i = 0; i < items.size(); i++) { + final FileItem item = (FileItem) items.get(i); + if (item.isFormField()) { + // Process only form fields - no file upload items + parameters.put(item.getFieldName(), item.getString("UTF-8")); + + // log requests on trace + if (log.isTraceEnabled()) { + final String logString = item.getString("UTF-8"); + + // TODO use RegExp + final String startS = "<pr:Identification><pr:Value>"; + final String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>"; + String logWithMaskedBaseid = logString; + final int start = logString.indexOf(startS); + if (start > -1) { + final int end = logString.indexOf(endS); + if (end > -1) { + logWithMaskedBaseid = logString.substring(0, start); + logWithMaskedBaseid += startS; + logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx"; + logWithMaskedBaseid += logString.substring(end, logString.length()); + } + } + + log.debug("Processed multipart/form-data request parameter: \nName: " + + item.getFieldName() + "\nValue: " + logWithMaskedBaseid); + } + + } + } + + } else { + final Iterator<Entry<String, String[]>> requestParamIt = + req.getParameterMap().entrySet().iterator(); + while (requestParamIt.hasNext()) { + final Entry<String, String[]> entry = requestParamIt.next(); + final String key = entry.getKey(); + final String[] values = entry.getValue(); + // take the last value from the value array since the legacy code above also + // does it this + // way + parameters.put(key, ArrayUtils.isEmpty(values) ? null : values[values.length - 1]); + } + + } + + return parameters; + } + + /** + * Reads bytes up to a delimiter, consuming the delimiter. + * + * @param in input stream + * @param delimiter delimiter character + * @return String constructed from the read bytes + * @throws IOException In case of a general error + */ + protected String readBytesUpTo(final InputStream in, final char delimiter) throws IOException { + final ByteArrayOutputStream bout = new ByteArrayOutputStream(); + boolean done = false; + int b; + while (!done && (b = in.read()) >= 0) { + if (b == delimiter) { + done = true; + } else { + bout.write(b); + } + } + return bout.toString("UTF-8"); + + } + + /** + * Adds a parameter to a URL. + * + * @param url the URL + * @param paramname parameter name + * @param paramvalue parameter value + * @return the URL with parameter added + */ + protected static String addUrlParameter(final String url, final String paramname, + final String paramvalue) { + final String param = paramname + "=" + paramvalue; + if (url.indexOf("?") < 0) { + return url + "?" + param; + } else { + return url + "&" + param; + } + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/ModuleRegistration.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/ModuleRegistration.java index 6789c802..c4f1b505 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/ModuleRegistration.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/ModuleRegistration.java @@ -1,36 +1,28 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.auth.modules; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -58,122 +50,114 @@ import at.gv.egiz.eaaf.core.impl.idp.process.ProcessDefinitionParserException; */ public class ModuleRegistration { - private static ModuleRegistration instance = new ModuleRegistration(); - - private final List<AuthModule> priorizedModules = new ArrayList<>(); - - @Autowired - private ApplicationContext ctx; - - @Autowired - private ProcessEngine processEngine; - - private final Logger log = LoggerFactory.getLogger(getClass()); - - public static ModuleRegistration getInstance() { - return instance; - } - - private ModuleRegistration() { - } - - @PostConstruct - private void init() { - // load modules via the ServiceLoader - initServiceLoaderModules(); - - // load modules via Spring - initSpringModules(); - - // order modules according to their priority - sortModules(); - - instance = this; - } - - /** - * Discovers modules which use the ServiceLoader mechanism. - */ - private void initServiceLoaderModules() { - log.info("Looking for auth modules."); - final ServiceLoader<AuthModule> loader = ServiceLoader.load(AuthModule.class); - final Iterator<AuthModule> modules = loader.iterator(); - while (modules.hasNext()) { - final AuthModule module = modules.next(); - log.info("Detected module {}", module.getClass().getName()); - registerModuleProcessDefinitions(module); - priorizedModules.add(module); - } - } - - /** - * Discovers modules which use Spring. - */ - private void initSpringModules() { - log.debug("Discovering Spring modules."); - final Map<String, AuthModule> modules = ctx.getBeansOfType(AuthModule.class); - for (final AuthModule module : modules.values()) { - registerModuleProcessDefinitions(module); - priorizedModules.add(module); - } - } - - /** - * Registers the resource uris for the module. - * - * @param module - * the module. - */ - private void registerModuleProcessDefinitions(AuthModule module) { - for (final String uri : module.getProcessDefinitions()) { - final Resource resource = ctx.getResource(uri); - if (resource.isReadable()) { - log.info("Registering process definition '{}'.", uri); - try (InputStream processDefinitionInputStream = resource.getInputStream()) { - processEngine.registerProcessDefinition(processDefinitionInputStream); - } catch (final IOException e) { - log.error("Process definition '{}' could NOT be read.", uri, e); - } catch (final ProcessDefinitionParserException e) { - log.error("Error while parsing process definition '{}'", uri, e); - } - } else { - log.error("Process definition '{}' cannot be read.", uri); - } - } - } - - /** - * Order the modules in descending order according to their priority. - */ - private void sortModules() { - Collections.sort(priorizedModules, new Comparator<AuthModule>() { - @Override - public int compare(AuthModule thisAuthModule, AuthModule otherAuthModule) { - final int thisOrder = thisAuthModule.getPriority(); - final int otherOrder = otherAuthModule.getPriority(); - return (thisOrder < otherOrder ? 1 : (thisOrder == otherOrder ? 0 : -1)); - } - }); - } - - /** - * Returns the process description id of the first process, in the highest ranked - * module, which is able to work with the given execution context. - * - * @param context - * the {@link ExecutionContext}. - * @param pendingReq the current processed {@link IRequest} - * @return the process id or {@code null} - */ - public String selectProcess(ExecutionContext context, IRequest pendingReq) { - for (final AuthModule module : priorizedModules) { - final String id = module.selectProcess(context, pendingReq); - if (StringUtils.isNotEmpty(id)) { - log.debug("Process with id '{}' selected, for context '{}'.", id, context); - return id; - } - } - log.info("No process is able to handle context '{}'.", context); - return null; - } + // private static ModuleRegistration instance = new ModuleRegistration(); + + private final List<AuthModule> priorizedModules = new ArrayList<>(); + + @Autowired + private ApplicationContext ctx; + + @Autowired + private ProcessEngine processEngine; + + private final Logger log = LoggerFactory.getLogger(getClass()); + + private ModuleRegistration() { + + } + + @PostConstruct + private void init() { + // load modules via the ServiceLoader + initServiceLoaderModules(); + + // load modules via Spring + initSpringModules(); + + // order modules according to their priority + sortModules(); + + // instance = this; + } + + /** + * Discovers modules which use the ServiceLoader mechanism. + */ + private void initServiceLoaderModules() { + log.info("Looking for auth modules."); + final ServiceLoader<AuthModule> loader = ServiceLoader.load(AuthModule.class); + final Iterator<AuthModule> modules = loader.iterator(); + while (modules.hasNext()) { + final AuthModule module = modules.next(); + log.info("Detected module {}", module.getClass().getName()); + registerModuleProcessDefinitions(module); + priorizedModules.add(module); + } + } + + /** + * Discovers modules which use Spring. + */ + private void initSpringModules() { + log.debug("Discovering Spring modules."); + final Map<String, AuthModule> modules = ctx.getBeansOfType(AuthModule.class); + for (final AuthModule module : modules.values()) { + registerModuleProcessDefinitions(module); + priorizedModules.add(module); + } + } + + /** + * Registers the resource uris for the module. + * + * @param module the module. + */ + private void registerModuleProcessDefinitions(final AuthModule module) { + for (final String uri : module.getProcessDefinitions()) { + final Resource resource = ctx.getResource(uri); + if (resource.isReadable()) { + log.info("Registering process definition '{}'.", uri); + try (InputStream processDefinitionInputStream = resource.getInputStream()) { + processEngine.registerProcessDefinition(processDefinitionInputStream); + } catch (final IOException e) { + log.error("Process definition '{}' could NOT be read.", uri, e); + } catch (final ProcessDefinitionParserException e) { + log.error("Error while parsing process definition '{}'", uri, e); + } + } else { + log.error("Process definition '{}' cannot be read.", uri); + } + } + } + + /** + * Order the modules in descending order according to their priority. + */ + private void sortModules() { + Collections.sort(priorizedModules, (thisAuthModule, otherAuthModule) -> { + final int thisOrder = thisAuthModule.getPriority(); + final int otherOrder = otherAuthModule.getPriority(); + return thisOrder < otherOrder ? 1 : thisOrder == otherOrder ? 0 : -1; + }); + } + + /** + * Returns the process description id of the first process, in the highest + * ranked module, which is able to work with the given execution context. + * + * @param context the {@link ExecutionContext}. + * @param pendingReq the current processed {@link IRequest} + * @return the process id or {@code null} + */ + public String selectProcess(final ExecutionContext context, final IRequest pendingReq) { + for (final AuthModule module : priorizedModules) { + final String id = module.selectProcess(context, pendingReq); + if (StringUtils.isNotEmpty(id)) { + log.debug("Process with id '{}' selected, for context '{}'.", id, context); + return id; + } + } + log.info("No process is able to handle context '{}'.", context); + return null; + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java index 2edf8a75..817c7aa2 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java @@ -1,25 +1,22 @@ -/******************************************************************************* - * Copyright 2019 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2019 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.auth.services; import java.io.IOException; @@ -47,479 +44,494 @@ import at.gv.egiz.components.eventlog.api.EventConstants; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IRequestStorage; import at.gv.egiz.eaaf.core.api.IStatusMessenger; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfiguration; -import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfigurationFactory; -import at.gv.egiz.eaaf.core.api.gui.IGUIFormBuilder; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.api.gui.IGuiFormBuilder; import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; import at.gv.egiz.eaaf.core.api.idp.IAction; 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.IModulInfo; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.api.idp.auth.IAuthenticationManager; -import at.gv.egiz.eaaf.core.api.idp.auth.ISSOManager; +import at.gv.egiz.eaaf.core.api.idp.auth.ISsoManager; import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService; -import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; +import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface; import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger; import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.exceptions.EAAFSSOException; -import at.gv.egiz.eaaf.core.exceptions.GUIBuildException; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafSsoException; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; import at.gv.egiz.eaaf.core.exceptions.ProtocolNotActiveException; -import at.gv.egiz.eaaf.core.impl.gui.AbstractGUIFormBuilderConfiguration; +import at.gv.egiz.eaaf.core.impl.gui.AbstractGuiFormBuilderConfiguration; import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; -import at.gv.egiz.eaaf.core.impl.utils.HTTPUtils; +import at.gv.egiz.eaaf.core.impl.utils.HttpUtils; @Service public class ProtocolAuthenticationService implements IProtocolAuthenticationService { - private static final Logger log = LoggerFactory.getLogger(ProtocolAuthenticationService.class); - - private static final List<String> ERROR_LOGGER_ON_INFO_LEVEL = - Arrays.asList( - IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP - ); - - @Autowired(required=true) private ApplicationContext applicationContext; - @Autowired(required=true) private IAuthenticationManager authmanager; - @Autowired(required=true) private IAuthenticationDataBuilder authDataBuilder; - @Autowired(required=true) private IGUIBuilderConfigurationFactory guiConfigFactory; - @Autowired(required=true) private IStatusMessenger statusMessager; - @Autowired(required=true) private IRequestStorage requestStorage; - @Autowired(required=true) IPendingRequestIdGenerationStrategy pendingReqIdGenerationStrategy; - - @Autowired(required=false) private ISSOManager ssoManager; - @Autowired private IStatisticLogger statisticLogger; - @Autowired private IRevisionLogger revisionsLogger; - - - private IGUIFormBuilder guiBuilder; - - /* (non-Javadoc) - * @see at.gv.egiz.eaaf.core.impl.idp.auth.services.IProtocolAuthenticationService#performAuthentication(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egiz.eaaf.core.api.IRequest) - */ - @Override - public void performAuthentication(final HttpServletRequest req, final HttpServletResponse resp, - final IRequest pendingReq) throws IOException, EAAFException { - try { - if (pendingReq.isNeedAuthentication()) { - //request needs authentication --> start authentication process ... - - //set pendingRequestId to support asynchrony message-processing - ((RequestImpl)pendingReq).setPendingRequestId(pendingReqIdGenerationStrategy.generateExternalPendingRequestId()); - - //load Parameters from OnlineApplicationConfiguration - final ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); - - if (oaParam == null) - throw new EAAFAuthenticationException( - IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG, - new Object[] { pendingReq.getSPEntityId() }); - - if (authmanager.doAuthentication(req, resp, pendingReq)) { - //pending request is already authenticated --> protocol-specific postProcessing can start directly - finalizeAuthentication(req, resp, pendingReq); - - //transaction is finished, log transaction finished event - revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); - - } - - } else { - executeProtocolSpecificAction(req, resp, pendingReq, null); - - } - - } catch (final Exception e) { - buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); - authmanager.performOnlyIDPLogOut(req, resp, pendingReq); - - } - } - - /* (non-Javadoc) - * @see at.gv.egiz.eaaf.core.impl.idp.auth.services.IProtocolAuthenticationService#finalizeAuthentication(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egiz.eaaf.core.api.IRequest) - */ - @Override - public void finalizeAuthentication(final HttpServletRequest req, final HttpServletResponse resp, final IRequest pendingReq) throws EAAFException, IOException{ - log.debug("Finalize PendingRequest with ID " + pendingReq.getPendingRequestId()); - try { - - //check if pending-request has 'abortedByUser' flag set - if (pendingReq.isAbortedByUser()) { - //send authentication aborted error to Service Provider - buildProtocolSpecificErrorResponse( - new EAAFAuthenticationException( - IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP, - new Object[] {}), - req, resp, pendingReq); - - //do not remove the full active SSO-Session - // in case of only one Service-Provider authentication request is aborted - if ( !pendingReq.needSingleSignOnFunctionality()) { - requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); - - } - - //check if pending-request are authenticated - } else if (pendingReq.isAuthenticated() && !pendingReq.isNeedUserConsent()) { - internalFinalizeAuthenticationProcess(req, resp, pendingReq); - - } else { - //suspect state: pending-request is not aborted but also are not authenticated - log.warn("PendingRequest flag for 'authenticated':{} and 'needConsent':{}", pendingReq.isAuthenticated(), pendingReq.isNeedUserConsent()); - if (pendingReq.isNeedUserConsent()) { - log.error("PendingRequest NEEDS user-consent. Can NOT fininalize authentication --> Abort authentication process!"); - - } else { - log.error("PendingRequest is NOT authenticated --> Abort authentication process!"); - - } - - handleErrorNoRedirect( - new EAAFException( - "auth.20", - null), req, resp, true); - - } - - } catch (final Exception e) { - log.error("Finalize authentication protocol FAILED." , e); - buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); - - } - - //remove pending-request - if (pendingReq != null) { - requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); - revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); - - } - } - - - @Override - public void buildProtocolSpecificErrorResponse(final Throwable throwable, final HttpServletRequest req, - final HttpServletResponse resp, final IRequest protocolRequest) throws EAAFException, IOException { - try { - - final Class<?> clazz = Class.forName(protocolRequest.requestedModule()); - - if (clazz == null || - !IModulInfo.class.isAssignableFrom(clazz)) { - log.error("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); - throw new Exception("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); - - } - - final IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz); - - if (handlingModule.generateErrorMessage( - throwable, req, resp, protocolRequest)) { - - //log Error to technical log - logExceptionToTechnicalLog(throwable); - - //log Error Message - statisticLogger.logErrorOperation(throwable, protocolRequest); - - //write revision log entries - revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, protocolRequest.getUniqueTransactionIdentifier()); - - return; - - } else { - handleErrorNoRedirect(throwable, req, resp, true); - - } - - } catch (final Throwable e) { - handleErrorNoRedirect(throwable, req, resp, true); - - } - - } - - @Override - public void handleErrorNoRedirect(final Throwable throwable, final HttpServletRequest req, - final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) throws IOException, EAAFException { - - //log Exception into statistic database - if (writeExceptionToStatisticLog) - statisticLogger.logErrorOperation(throwable); - - //write errror to console - logExceptionToTechnicalLog(throwable); - - //return error to Web browser - if (throwable instanceof EAAFException || throwable instanceof ProcessExecutionException) - internalMOAIDExceptionHandler(req, resp, (Exception)throwable, false); - - else { - //write generic message for general exceptions - final String msg = statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null); - writeHTMLErrorResponse(req, resp, msg, "9199", null, (Exception) throwable); - - } - - } - - - public void setGuiBuilder(IGUIFormBuilder guiBuilder) { - this.guiBuilder = guiBuilder; - } - - /** - * Finalize the requested protocol operation - * - * @param httpReq HttpServletRequest - * @param httpResp HttpServletResponse - * @param protocolRequest Authentication request which is actually in process - * @param moaSession MOASession object, which is used to generate the protocol specific authentication information - * @throws Exception - */ - protected void internalFinalizeAuthenticationProcess(final HttpServletRequest req, final HttpServletResponse resp, - final IRequest pendingReq) throws Exception { - - String newSSOSessionId = null; - - //if Single Sign-On functionality is enabled for this request - if (pendingReq.needSingleSignOnFunctionality()) { - if (ssoManager != null) { - newSSOSessionId = ssoManager.createNewSSOSessionCookie(req, resp, pendingReq); - if (StringUtils.isEmpty(pendingReq.getInternalSSOSessionIdentifier())) - ssoManager.createNewSSOSession(pendingReq, newSSOSessionId); - - } else - log.warn("SSO is requested but there is not SSO Session-Manager available"); - - } - - //build authenticationdata from session information and OA configuration - final IAuthData authData = authDataBuilder.buildAuthenticationData(pendingReq); - - //execute the protocol-specific action - final SLOInformationInterface sloInformation = executeProtocolSpecificAction(req, resp, pendingReq, authData); - - //Store OA specific SSO session information if an SSO cookie is set - if (StringUtils.isNotEmpty(newSSOSessionId)) { - try { - ssoManager.updateSSOSession(pendingReq, newSSOSessionId, sloInformation); - - } catch (final EAAFSSOException e) { - log.warn("SSO Session information can not be stored -> SSO is not enabled!"); - authmanager.performOnlyIDPLogOut(req, resp, pendingReq); - - } - - } else { - //remove MOASession from database - authmanager.performOnlyIDPLogOut(req, resp, pendingReq); - - } - - //Advanced statistic logging - statisticLogger.logSuccessOperation(pendingReq, authData, StringUtils.isNotEmpty(newSSOSessionId)); - - } - - /** - * Executes the requested protocol action - * - * @param httpReq HttpServletRequest - * @param httpResp HttpServletResponse - * @param protocolRequest Authentication request which is actually in process - * @param authData Service-provider specific authentication data - * - * @return Return Single LogOut information or null if protocol supports no SSO - * - * @throws Exception - */ - private SLOInformationInterface executeProtocolSpecificAction(final HttpServletRequest httpReq, final HttpServletResponse httpResp, - final IRequest pendingReq, final IAuthData authData) throws Exception { - try { - // request needs no authentication --> start request processing - final Class<?> clazz = Class.forName(pendingReq.requestedAction()); - if (clazz == null || - !IAction.class.isAssignableFrom(clazz)) { - log.error("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); - throw new Exception("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); - - } - - final IAction protocolAction = (IAction) applicationContext.getBean(clazz); - return protocolAction.processRequest(pendingReq, httpReq, httpResp, authData); - - } catch (final ClassNotFoundException e) { - log.error("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); - throw new Exception("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); - } - - } - - /** - * Write a Exception to the MOA-ID-Auth internal technical log - * - * @param loggedException Exception to log - */ - protected void logExceptionToTechnicalLog(final Throwable loggedException) { - if (!( loggedException instanceof EAAFException - || loggedException instanceof ProcessExecutionException )) { - log.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException); - - } else { - if (loggedException instanceof EAAFAuthenticationException && - ERROR_LOGGER_ON_INFO_LEVEL.contains( - ((EAAFAuthenticationException) loggedException).getErrorId())) { - if (log.isDebugEnabled() || log.isTraceEnabled()) { - log.info(loggedException.getMessage(), loggedException); - - } else { - log.info(loggedException.getMessage()); - - } - - } else { - if (log.isDebugEnabled() || log.isTraceEnabled()) { - log.warn(loggedException.getMessage(), loggedException); - - } else { - log.warn(loggedException.getMessage()); - - } - } - } - } - - private void writeHTMLErrorResponse(@NonNull final HttpServletRequest httpReq, @NonNull final HttpServletResponse httpResp, - @NonNull final String msg, @NonNull final String errorCode, @Nullable final Object[] params, @NonNull final Exception error) throws IOException, EAAFException { - - try { - final IGUIBuilderConfiguration config - = guiConfigFactory.getDefaultErrorGUI(HTTPUtils.extractAuthURLFromRequest(httpReq)); - - - String[] errorCodeParams = null; - if (params == null) - errorCodeParams = new String[] {}; - else { - errorCodeParams = new String[params.length]; - for (int i=0; i<params.length; i++) { - if (params[i] != null) - errorCodeParams[i] = params[i].toString(); - else - errorCodeParams[i] = "null"; - - } - } - - - - //add errorcode and errormessage - if (config instanceof ModifyableGuiBuilderConfiguration) { - ((ModifyableGuiBuilderConfiguration)config) - .putCustomParameter(AbstractGUIFormBuilderConfiguration.PARAM_GROUP_MSG, - PARAM_GUI_ERROMSG, msg); - ((ModifyableGuiBuilderConfiguration)config) - .putCustomParameter(AbstractGUIFormBuilderConfiguration.PARAM_GROUP_MSG, - PARAM_GUI_ERRORCODE, errorCode); - ((ModifyableGuiBuilderConfiguration)config) - .putCustomParameterWithOutEscaption(AbstractGUIFormBuilderConfiguration.PARAM_GROUP_MSG, - PARAM_GUI_ERRORCODEPARAMS, ArrayUtils.toString(errorCodeParams)); - - //add stacktrace if debug is enabled - if (log.isTraceEnabled()) { - ((ModifyableGuiBuilderConfiguration)config) - .putCustomParameter(AbstractGUIFormBuilderConfiguration.PARAM_GROUP_MSG, - PARAM_GUI_ERRORSTACKTRACE, getStacktraceFromException(error)); - - } - - } else - log.info("Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); - - - - guiBuilder.build(httpReq, httpResp, config, "Error-Message"); - - } catch (final GUIBuildException e) { - log.warn("Can not build error-message GUI.", e); - throw new EAAFException("9199", null, e); - - - } - - } - - private String getStacktraceFromException(final Exception ex) { - final StringWriter errors = new StringWriter(); - ex.printStackTrace(new PrintWriter(errors)); - return errors.toString(); - - } - - private void internalMOAIDExceptionHandler(final HttpServletRequest req, final HttpServletResponse resp, final Exception e, final boolean writeExceptionToStatisicLog) throws IOException, EAAFException { - if (e instanceof ProtocolNotActiveException) { - resp.getWriter().write(e.getMessage()); - resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); - resp.sendError(HttpServletResponse.SC_FORBIDDEN, - StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage()))); - - } else if (e instanceof AuthnRequestValidatorException) { - final AuthnRequestValidatorException ex = (AuthnRequestValidatorException)e; - //log Error Message - if (writeExceptionToStatisicLog) - statisticLogger.logErrorOperation(ex, ex.getErrorRequest()); - - //write error message - //writeBadRequestErrorResponse(req, resp, (EAAFException) e); - writeHTMLErrorResponse(req, resp, - e.getMessage(), - statusMessager.getResponseErrorCode(e), - null, - e); - - } else if (e instanceof InvalidProtocolRequestException) { - //send error response - //writeBadRequestErrorResponse(req, resp, (EAAFException) e); - writeHTMLErrorResponse(req, resp, - e.getMessage(), - statusMessager.getResponseErrorCode(e), - null, - e); - - } else if (e instanceof ConfigurationException) { - //send HTML formated error message - writeHTMLErrorResponse(req, resp, - e.getMessage(), - statusMessager.getResponseErrorCode(e), - null, - e); - - } else if (e instanceof EAAFException) { - //send HTML formated error message - writeHTMLErrorResponse(req, resp, - e.getMessage(), - statusMessager.getResponseErrorCode(e), - ((EAAFException) e).getParams(), - e); - - } else if (e instanceof ProcessExecutionException) { - //send HTML formated error message - writeHTMLErrorResponse(req, resp, - e.getMessage(), - statusMessager.getResponseErrorCode(e), - null, - e); - - } - - } - - + private static final Logger log = LoggerFactory.getLogger(ProtocolAuthenticationService.class); + + private static final List<String> ERROR_LOGGER_ON_INFO_LEVEL = + Arrays.asList(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP); + + @Autowired(required = true) + private ApplicationContext applicationContext; + @Autowired(required = true) + private IAuthenticationManager authmanager; + @Autowired(required = true) + private IAuthenticationDataBuilder authDataBuilder; + @Autowired(required = true) + private IGuiBuilderConfigurationFactory guiConfigFactory; + @Autowired(required = true) + private IStatusMessenger statusMessager; + @Autowired(required = true) + private IRequestStorage requestStorage; + @Autowired(required = true) + IPendingRequestIdGenerationStrategy pendingReqIdGenerationStrategy; + + @Autowired(required = false) + private ISsoManager ssoManager; + @Autowired + private IStatisticLogger statisticLogger; + @Autowired + private IRevisionLogger revisionsLogger; + + private IGuiFormBuilder guiBuilder; + + /* + * (non-Javadoc) + * + * @see + * at.gv.egiz.eaaf.core.impl.idp.auth.services.IProtocolAuthenticationService# + * performAuthentication(javax.servlet.http.HttpServletRequest, + * javax.servlet.http.HttpServletResponse, at.gv.egiz.eaaf.core.api.IRequest) + */ + @Override + public void performAuthentication(final HttpServletRequest req, final HttpServletResponse resp, + final IRequest pendingReq) throws IOException, EaafException { + try { + if (pendingReq.isNeedAuthentication()) { + // request needs authentication --> start authentication process ... + + // set pendingRequestId to support asynchrony message-processing + ((RequestImpl) pendingReq) + .setPendingRequestId(pendingReqIdGenerationStrategy.generateExternalPendingRequestId()); + + // load Parameters from OnlineApplicationConfiguration + final ISpConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); + + if (oaParam == null) { + throw new EaafAuthenticationException( + IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG, + new Object[] { pendingReq.getSpEntityId() }); + } + + if (authmanager.doAuthentication(req, resp, pendingReq)) { + // pending request is already authenticated --> protocol-specific postProcessing + // can start + // directly + finalizeAuthentication(req, resp, pendingReq); + + // transaction is finished, log transaction finished event + revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, + pendingReq.getUniqueTransactionIdentifier()); + + } + + } else { + executeProtocolSpecificAction(req, resp, pendingReq, null); + + } + + } catch (final Exception e) { + buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); + authmanager.performOnlyIdpLogOut(req, resp, pendingReq); + + } + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egiz.eaaf.core.impl.idp.auth.services.IProtocolAuthenticationService# + * finalizeAuthentication(javax.servlet.http.HttpServletRequest, + * javax.servlet.http.HttpServletResponse, at.gv.egiz.eaaf.core.api.IRequest) + */ + @Override + public void finalizeAuthentication(final HttpServletRequest req, final HttpServletResponse resp, + final IRequest pendingReq) throws EaafException, IOException { + log.debug("Finalize PendingRequest with ID " + pendingReq.getPendingRequestId()); + try { + + // check if pending-request has 'abortedByUser' flag set + if (pendingReq.isAbortedByUser()) { + // send authentication aborted error to Service Provider + buildProtocolSpecificErrorResponse( + new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP, + new Object[] {}), + req, resp, pendingReq); + + // do not remove the full active SSO-Session + // in case of only one Service-Provider authentication request is aborted + if (!pendingReq.needSingleSignOnFunctionality()) { + requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); + + } + + // check if pending-request are authenticated + } else if (pendingReq.isAuthenticated() && !pendingReq.isNeedUserConsent()) { + internalFinalizeAuthenticationProcess(req, resp, pendingReq); + + } else { + // suspect state: pending-request is not aborted but also are not authenticated + log.warn("PendingRequest flag for 'authenticated':{} and 'needConsent':{}", + pendingReq.isAuthenticated(), pendingReq.isNeedUserConsent()); + if (pendingReq.isNeedUserConsent()) { + log.error( + "PendingRequest NEEDS user-consent. Can NOT fininalize authentication --> Abort authentication process!"); + + } else { + log.error("PendingRequest is NOT authenticated --> Abort authentication process!"); + + } + + handleErrorNoRedirect(new EaafException("auth.20", null), req, resp, true); + + } + + } catch (final Exception e) { + log.error("Finalize authentication protocol FAILED.", e); + buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); + + } + + // remove pending-request + requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, + pendingReq.getUniqueTransactionIdentifier()); + + } + + @Override + public void buildProtocolSpecificErrorResponse(final Throwable throwable, + final HttpServletRequest req, final HttpServletResponse resp, final IRequest protocolRequest) + throws EaafException, IOException { + try { + + final Class<?> clazz = Class.forName(protocolRequest.requestedModule()); + + if (clazz == null || !IModulInfo.class.isAssignableFrom(clazz)) { + log.error( + "Requested protocol module Class is NULL or does not implement the IModulInfo interface."); + throw new Exception( + "Requested protocol module Class is NULL or does not implement the IModulInfo interface."); + + } + + final IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz); + + if (handlingModule.generateErrorMessage(throwable, req, resp, protocolRequest)) { + + // log Error to technical log + logExceptionToTechnicalLog(throwable); + + // log Error Message + statisticLogger.logErrorOperation(throwable, protocolRequest); + + // write revision log entries + revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, + protocolRequest.getUniqueTransactionIdentifier()); + + return; + + } else { + handleErrorNoRedirect(throwable, req, resp, true); + + } + + } catch (final Throwable e) { + handleErrorNoRedirect(throwable, req, resp, true); + + } + + } + + @Override + public void handleErrorNoRedirect(final Throwable throwable, final HttpServletRequest req, + final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) + throws IOException, EaafException { + + // log Exception into statistic database + if (writeExceptionToStatisticLog) { + statisticLogger.logErrorOperation(throwable); + } + + // write errror to console + logExceptionToTechnicalLog(throwable); + + // return error to Web browser + if (throwable instanceof EaafException || throwable instanceof ProcessExecutionException) { + internalMoaidExceptionHandler(req, resp, (Exception) throwable, false); + } else { + // write generic message for general exceptions + final String msg = + statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null); + writeHtmlErrorResponse(req, resp, msg, "9199", null, (Exception) throwable); + + } + + } + + public void setGuiBuilder(final IGuiFormBuilder guiBuilder) { + this.guiBuilder = guiBuilder; + } + + /** + * Finalize the requested protocol operation. + * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param protocolRequest Authentication request which is actually in process + * @param moaSession MOASession object, which is used to generate the + * protocol specific authentication information + * @throws Exception In case of an error + */ + protected void internalFinalizeAuthenticationProcess(final HttpServletRequest req, + final HttpServletResponse resp, final IRequest pendingReq) throws Exception { + + String newSsoSessionId = null; + + // if Single Sign-On functionality is enabled for this request + if (pendingReq.needSingleSignOnFunctionality()) { + if (ssoManager != null) { + newSsoSessionId = ssoManager.createNewSsoSessionCookie(req, resp, pendingReq); + if (StringUtils.isEmpty(pendingReq.getInternalSsoSessionIdentifier())) { + ssoManager.createNewSsoSession(pendingReq, newSsoSessionId); + } + + } else { + log.warn("SSO is requested but there is not SSO Session-Manager available"); + } + + } + + // build authenticationdata from session information and OA configuration + final IAuthData authData = authDataBuilder.buildAuthenticationData(pendingReq); + + // execute the protocol-specific action + final SloInformationInterface sloInformation = + executeProtocolSpecificAction(req, resp, pendingReq, authData); + + // Store OA specific SSO session information if an SSO cookie is set + if (StringUtils.isNotEmpty(newSsoSessionId)) { + try { + ssoManager.updateSsoSession(pendingReq, newSsoSessionId, sloInformation); + + } catch (final EaafSsoException e) { + log.warn("SSO Session information can not be stored -> SSO is not enabled!"); + authmanager.performOnlyIdpLogOut(req, resp, pendingReq); + + } + + } else { + // remove MOASession from database + authmanager.performOnlyIdpLogOut(req, resp, pendingReq); + + } + + // Advanced statistic logging + statisticLogger.logSuccessOperation(pendingReq, authData, + StringUtils.isNotEmpty(newSsoSessionId)); + + } + + /** + * Executes the requested protocol action. + * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param protocolRequest Authentication request which is actually in process + * @param authData Service-provider specific authentication data + * + * @return Return Single LogOut information or null if protocol supports no SSO + * + * @throws Exception in case of an error + */ + private SloInformationInterface executeProtocolSpecificAction(final HttpServletRequest httpReq, + final HttpServletResponse httpResp, final IRequest pendingReq, final IAuthData authData) + throws Exception { + try { + // request needs no authentication --> start request processing + final Class<?> clazz = Class.forName(pendingReq.requestedAction()); + if (clazz == null || !IAction.class.isAssignableFrom(clazz)) { + log.error( + "Requested protocol-action processing Class is NULL or does not implement the IAction interface."); + throw new Exception( + "Requested protocol-action processing Class is NULL or does not implement the IAction interface."); + + } + + final IAction protocolAction = (IAction) applicationContext.getBean(clazz); + return protocolAction.processRequest(pendingReq, httpReq, httpResp, authData); + + } catch (final ClassNotFoundException e) { + log.error( + "Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); + throw new Exception( + "Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); + } + + } + + /** + * Write a Exception to the MOA-ID-Auth internal technical log. + * + * @param loggedException Exception to log + */ + protected void logExceptionToTechnicalLog(final Throwable loggedException) { + if (!(loggedException instanceof EaafException + || loggedException instanceof ProcessExecutionException)) { + log.error("Receive an internal error: Message=" + loggedException.getMessage(), + loggedException); + + } else { + if (loggedException instanceof EaafAuthenticationException && ERROR_LOGGER_ON_INFO_LEVEL + .contains(((EaafAuthenticationException) loggedException).getErrorId())) { + if (log.isDebugEnabled() || log.isTraceEnabled()) { + log.info(loggedException.getMessage(), loggedException); + + } else { + log.info(loggedException.getMessage()); + + } + + } else { + if (log.isDebugEnabled() || log.isTraceEnabled()) { + log.warn(loggedException.getMessage(), loggedException); + + } else { + log.warn(loggedException.getMessage()); + + } + } + } + } + + private void writeHtmlErrorResponse(@NonNull final HttpServletRequest httpReq, + @NonNull final HttpServletResponse httpResp, @NonNull final String msg, + @NonNull final String errorCode, @Nullable final Object[] params, + @NonNull final Exception error) throws IOException, EaafException { + + try { + final IGuiBuilderConfiguration config = + guiConfigFactory.getDefaultErrorGui(HttpUtils.extractAuthUrlFromRequest(httpReq)); + + String[] errorCodeParams = null; + if (params == null) { + errorCodeParams = new String[] {}; + } else { + errorCodeParams = new String[params.length]; + for (int i = 0; i < params.length; i++) { + if (params[i] != null) { + errorCodeParams[i] = params[i].toString(); + } else { + errorCodeParams[i] = "null"; + } + + } + } + + // add errorcode and errormessage + if (config instanceof ModifyableGuiBuilderConfiguration) { + ((ModifyableGuiBuilderConfiguration) config).putCustomParameter( + AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERROMSG, msg); + ((ModifyableGuiBuilderConfiguration) config).putCustomParameter( + AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODE, errorCode); + ((ModifyableGuiBuilderConfiguration) config).putCustomParameterWithOutEscaption( + AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODEPARAMS, + ArrayUtils.toString(errorCodeParams)); + + // add stacktrace if debug is enabled + if (log.isTraceEnabled()) { + ((ModifyableGuiBuilderConfiguration) config).putCustomParameter( + AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORSTACKTRACE, + getStacktraceFromException(error)); + + } + + } else { + log.info( + "Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); + } + + guiBuilder.build(httpReq, httpResp, config, "Error-Message"); + + } catch (final GuiBuildException e) { + log.warn("Can not build error-message GUI.", e); + throw new EaafException("9199", null, e); + + } + + } + + private String getStacktraceFromException(final Exception ex) { + final StringWriter errors = new StringWriter(); + ex.printStackTrace(new PrintWriter(errors)); + return errors.toString(); + + } + + private void internalMoaidExceptionHandler(final HttpServletRequest req, + final HttpServletResponse resp, final Exception e, final boolean writeExceptionToStatisicLog) + throws IOException, EaafException { + if (e instanceof ProtocolNotActiveException) { + resp.getWriter().write(e.getMessage()); + resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); + resp.sendError(HttpServletResponse.SC_FORBIDDEN, + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage()))); + + } else if (e instanceof AuthnRequestValidatorException) { + final AuthnRequestValidatorException ex = (AuthnRequestValidatorException) e; + // log Error Message + if (writeExceptionToStatisicLog) { + statisticLogger.logErrorOperation(ex, ex.getErrorRequest()); + } + + // write error message + // writeBadRequestErrorResponse(req, resp, (EAAFException) e); + writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), + null, e); + + } else if (e instanceof InvalidProtocolRequestException) { + // send error response + // writeBadRequestErrorResponse(req, resp, (EAAFException) e); + writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), + null, e); + + } else if (e instanceof ConfigurationException) { + // send HTML formated error message + writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), + null, e); + + } else if (e instanceof EaafException) { + // send HTML formated error message + writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), + ((EaafException) e).getParams(), e); + + } else if (e instanceof ProcessExecutionException) { + // send HTML formated error message + writeHtmlErrorResponse(req, resp, e.getMessage(), statusMessager.getResponseErrorCode(e), + null, e); + + } + + } + } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/SimpleStringAttributeGenerator.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/SimpleStringAttributeGenerator.java index 77bd9b8a..df4e97fc 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/SimpleStringAttributeGenerator.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/SimpleStringAttributeGenerator.java @@ -1,68 +1,83 @@ /* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * Copyright 2014 Federal Chancellery Austria MOA-ID has been developed in a cooperation between + * BRZ, the Federal Chancellery Austria - ICT staff unit, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: http://www.osor.eu/eupl/ * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. */ + package at.gv.egiz.eaaf.core.impl.idp.builder; import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; /** + * Simple String attribute generator that only generates attribute values as + * String. + * * @author tlenz * */ public class SimpleStringAttributeGenerator implements IAttributeGenerator<String> { - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator#buildStringAttribute(java.lang.String, java.lang.String, java.lang.String) - */ - @Override - public String buildStringAttribute(String friendlyName, String name, String value) { - return value; - - } + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator# + * buildStringAttribute( java.lang.String, java.lang.String, java.lang.String) + */ + @Override + public String buildStringAttribute(final String friendlyName, final String name, final String value) { + return value; + + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator# + * buildIntegerAttribute (java.lang.String, java.lang.String, int) + */ + @Override + public String buildIntegerAttribute(final String friendlyName, final String name, final int value) { + return String.valueOf(value); + + } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator#buildIntegerAttribute(java.lang.String, java.lang.String, int) - */ - @Override - public String buildIntegerAttribute(String friendlyName, String name, int value) { - return String.valueOf(value); - - } + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator# + * buildLongAttribute( java.lang.String, java.lang.String, long) + */ + @Override + public String buildLongAttribute(final String friendlyName, final String name, final long value) { + return String.valueOf(value); - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator#buildLongAttribute(java.lang.String, java.lang.String, long) - */ - @Override - public String buildLongAttribute(String friendlyName, String name, long value) { - return String.valueOf(value); - - } + } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator#buildEmptyAttribute(java.lang.String, java.lang.String) - */ - @Override - public String buildEmptyAttribute(String friendlyName, String name) { - return null; - } + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator# + * buildEmptyAttribute( java.lang.String, java.lang.String) + */ + @Override + public String buildEmptyAttribute(final String friendlyName, final String name) { + return null; + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BPKAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BPKAttributeBuilder.java deleted file mode 100644 index 714ffc9d..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BPKAttributeBuilder.java +++ /dev/null @@ -1,123 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import javax.annotation.Nonnull; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.Assert; - -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; - -@PVPMETADATA -public class BPKAttributeBuilder implements IPVPAttributeBuilder { - - private static final Logger log = LoggerFactory.getLogger(BPKAttributeBuilder.class); - public static final String DELIMITER_BPKTYPE_BPK = ":"; - - @Override - public String getName() { - return BPK_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - final String result = getBpkForSP(authData); - log.trace("Authenticate user with bPK/wbPK: " + result); - return g.buildStringAttribute(BPK_FRIENDLY_NAME, BPK_NAME, result); - - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(BPK_FRIENDLY_NAME, BPK_NAME); - } - - /** - * Generate the bPK String for this specific SP - * - * @param authData - * @return - * @throws UnavailableAttributeException - */ - protected String getBpkForSP(IAuthData authData) throws UnavailableAttributeException { - final String bpk = attrMaxSize(authData.getBPK()); - final String type = removeBpkTypePrefix(authData.getBPKType()); - - if (StringUtils.isEmpty(bpk)) - throw new UnavailableAttributeException(BPK_NAME); - - return type + DELIMITER_BPKTYPE_BPK + bpk; - - } - - /** - * Limit the attribute value to maximum size - * - * @param attr - * @return - */ - protected String attrMaxSize(String attr) { - if (attr != null && attr.length() > BPK_MAX_LENGTH) { - attr = attr.substring(0, BPK_MAX_LENGTH); - } - return attr; - - } - - /** - * Remove bPKType prefix if available - * - * @param type - * @return - */ - @Nonnull - protected String removeBpkTypePrefix(@Nonnull String type) { - Assert.isTrue(type != null, "bPKType is 'NULL'"); - if (type.startsWith(EAAFConstants.URN_PREFIX_WBPK)) - return type.substring((EAAFConstants.URN_PREFIX_WBPK).length()); - - else if (type.startsWith(EAAFConstants.URN_PREFIX_CDID)) - return type.substring((EAAFConstants.URN_PREFIX_CDID).length()); - - else if (type.startsWith(EAAFConstants.URN_PREFIX_EIDAS)) - return type.substring((EAAFConstants.URN_PREFIX_EIDAS).length()); - - else - return type; - - } -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BirthdateAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BirthdateAttributeBuilder.java index c52a5d82..19500cb3 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BirthdateAttributeBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BirthdateAttributeBuilder.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; import java.text.DateFormat; @@ -31,37 +24,38 @@ import java.text.SimpleDateFormat; import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; -@PVPMETADATA -public class BirthdateAttributeBuilder implements IPVPAttributeBuilder { - - @Override - public String getName() { - return BIRTHDATE_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - - if (authData.getDateOfBirth() != null) { - final DateFormat pvpDateFormat = new SimpleDateFormat(BIRTHDATE_FORMAT_PATTERN); - final String dateString = pvpDateFormat.format(authData.getDateOfBirth()); - - return g.buildStringAttribute(BIRTHDATE_FRIENDLY_NAME, BIRTHDATE_NAME, dateString); - - } else - throw new UnavailableAttributeException(BIRTHDATE_NAME); - - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(BIRTHDATE_FRIENDLY_NAME, BIRTHDATE_NAME); - } - +@PvpMetadata +public class BirthdateAttributeBuilder implements IPvpAttributeBuilder { + + @Override + public String getName() { + return BIRTHDATE_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + + if (authData.getDateOfBirth() != null) { + final DateFormat pvpDateFormat = new SimpleDateFormat(BIRTHDATE_FORMAT_PATTERN); + final String dateString = pvpDateFormat.format(authData.getDateOfBirth()); + + return g.buildStringAttribute(BIRTHDATE_FRIENDLY_NAME, BIRTHDATE_NAME, dateString); + + } else { + throw new UnavailableAttributeException(BIRTHDATE_NAME); + } + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(BIRTHDATE_FRIENDLY_NAME, BIRTHDATE_NAME); + } + } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BpkAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BpkAttributeBuilder.java new file mode 100644 index 00000000..172d74a7 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BpkAttributeBuilder.java @@ -0,0 +1,96 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import javax.annotation.Nonnull; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Assert; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; + +@PvpMetadata +public class BpkAttributeBuilder implements IPvpAttributeBuilder { + + private static final Logger log = LoggerFactory.getLogger(BpkAttributeBuilder.class); + public static final String DELIMITER_BPKTYPE_BPK = ":"; + + @Override + public String getName() { + return BPK_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + final String result = getBpkForSP(authData); + log.trace("Authenticate user with bPK/wbPK: " + result); + return g.buildStringAttribute(BPK_FRIENDLY_NAME, BPK_NAME, result); + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(BPK_FRIENDLY_NAME, BPK_NAME); + } + + protected String getBpkForSP(final IAuthData authData) throws UnavailableAttributeException { + final String bpk = attrMaxSize(authData.getBpk()); + final String type = removeBpkTypePrefix(authData.getBpkType()); + + if (StringUtils.isEmpty(bpk)) { + throw new UnavailableAttributeException(BPK_NAME); + } + + return type + DELIMITER_BPKTYPE_BPK + bpk; + + } + + protected String attrMaxSize(String attr) { + if (attr != null && attr.length() > BPK_MAX_LENGTH) { + attr = attr.substring(0, BPK_MAX_LENGTH); + } + return attr; + + } + + @Nonnull + protected String removeBpkTypePrefix(@Nonnull final String type) { + Assert.isTrue(type != null, "bPKType is 'NULL'"); + if (type.startsWith(EaafConstants.URN_PREFIX_WBPK)) { + return type.substring(EaafConstants.URN_PREFIX_WBPK.length()); + } else if (type.startsWith(EaafConstants.URN_PREFIX_CDID)) { + return type.substring(EaafConstants.URN_PREFIX_CDID.length()); + } else if (type.startsWith(EaafConstants.URN_PREFIX_EIDAS)) { + return type.substring(EaafConstants.URN_PREFIX_EIDAS.length()); + } else { + return type; + } + + } +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDCcsURL.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDCcsURL.java deleted file mode 100644 index ec0f5d0c..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDCcsURL.java +++ /dev/null @@ -1,44 +0,0 @@ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; - -@PVPMETADATA -public class EIDCcsURL implements IPVPAttributeBuilder { - private static final Logger log = LoggerFactory.getLogger(EID_CCS_URL_NAME); - - @Override - public String getName() { - return EID_CCS_URL_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - if (authData instanceof IEidAuthData) { - final String bkuurl = ((IEidAuthData)authData).getVdaEndPointUrl(); - if (StringUtils.isNotEmpty(bkuurl)) - return g.buildStringAttribute(EID_CCS_URL_FRIENDLY_NAME, EID_CCS_URL_NAME, bkuurl); - - - } else - log.info(EID_CCS_URL_FRIENDLY_NAME + " is only available in MOA-ID context"); - - throw new UnavailableAttributeException(EID_CCS_URL_NAME); - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(EID_CCS_URL_FRIENDLY_NAME, EID_CCS_URL_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDEIDTokenBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDEIDTokenBuilder.java deleted file mode 100644 index 698393ea..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDEIDTokenBuilder.java +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * Copyright 2019 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.Base64Utils; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; - -@PVPMETADATA -public class EIDEIDTokenBuilder implements IPVPAttributeBuilder { - private static final Logger log = LoggerFactory.getLogger(EIDEIDTokenBuilder.class); - - - @Override - public String getName() { - return EID_E_ID_TOKEN_NAME; - } - - @Override - public <ATT> ATT build(final ISPConfiguration oaParam, final IAuthData authData, - final IAttributeGenerator<ATT> g) throws AttributeBuilderException { - - if (authData instanceof IEidAuthData) { - if (((IEidAuthData)authData).getEIDToken() == null) - throw new UnavailableAttributeException(EID_E_ID_TOKEN_NAME); - - return g.buildStringAttribute(EID_E_ID_TOKEN_FRIENDLY_NAME, - EID_E_ID_TOKEN_NAME, Base64Utils.encodeToString(((IEidAuthData)authData).getEIDToken())); - } else - log.info(EID_E_ID_TOKEN_FRIENDLY_NAME + " is only available in AuthHandler context"); - - throw new UnavailableAttributeException(EID_E_ID_TOKEN_NAME); - } - - @Override - public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(EID_E_ID_TOKEN_FRIENDLY_NAME, - EID_E_ID_TOKEN_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDEncryptedSourceIdAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDEncryptedSourceIdAttributeBuilder.java deleted file mode 100644 index 3fbdaf66..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDEncryptedSourceIdAttributeBuilder.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright 2019 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import at.gv.egiz.eaaf.core.api.data.ExtendedPVPAttributeDefinitions; -import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; - -public class EIDEncryptedSourceIdAttributeBuilder implements IAttributeBuilder, ExtendedPVPAttributeDefinitions { - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, IAttributeGenerator<ATT> g) - throws AttributeBuilderException { - return g.buildStringAttribute(getFriendlyName(), getName(), authData.getEncryptedSourceId()); - - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(getFriendlyName(), getName()); - - } - - @Override - public String getName() { - return EID_ENCRYPTED_SOURCEID_NAME; - } - - private String getFriendlyName() { - return EID_ENCRYPTED_SOURCEID_FRIENDLY_NAME; - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDEncryptedSourceIdTypeAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDEncryptedSourceIdTypeAttributeBuilder.java deleted file mode 100644 index 440ccf59..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDEncryptedSourceIdTypeAttributeBuilder.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright 2019 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import at.gv.egiz.eaaf.core.api.data.ExtendedPVPAttributeDefinitions; -import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; - -public class EIDEncryptedSourceIdTypeAttributeBuilder implements IAttributeBuilder, ExtendedPVPAttributeDefinitions { - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, IAttributeGenerator<ATT> g) - throws AttributeBuilderException { - return g.buildStringAttribute(getFriendlyName(), getName(), authData.getEncryptedSourceIdType()); - - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(getFriendlyName(), getName()); - - } - - @Override - public String getName() { - return EID_ENCRYPTED_SOURCEID_TYPE_NAME; - } - - private String getFriendlyName() { - return EID_ENCRYPTED_SOURCEID_TYPE_FRIENDLY_NAME; - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDIdentityLinkBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDIdentityLinkBuilder.java deleted file mode 100644 index 8a2cabbc..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDIdentityLinkBuilder.java +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.Base64Utils; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; - -@Deprecated -@PVPMETADATA -public class EIDIdentityLinkBuilder implements IPVPAttributeBuilder { - private static final Logger log = LoggerFactory.getLogger(EIDIdentityLinkBuilder.class); - - - public String getName() { - return EID_IDENTITY_LINK_NAME; - } - - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - try { - String ilAssertion = null; - if (authData.getIdentityLink() == null) - throw new UnavailableAttributeException(EID_IDENTITY_LINK_NAME); - - ilAssertion = authData.getIdentityLink().getSerializedSamlAssertion(); - - return g.buildStringAttribute(EID_IDENTITY_LINK_FRIENDLY_NAME, - EID_IDENTITY_LINK_NAME, Base64Utils.encodeToString(ilAssertion.getBytes("UTF-8"))); - - - } catch (IOException e) { - log.warn("IdentityLink serialization error.", e); - return g.buildEmptyAttribute(EID_IDENTITY_LINK_FRIENDLY_NAME, - EID_IDENTITY_LINK_NAME); - } - - } - - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(EID_IDENTITY_LINK_FRIENDLY_NAME, - EID_IDENTITY_LINK_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDIssuingNationAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDIssuingNationAttributeBuilder.java deleted file mode 100644 index a52197cb..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDIssuingNationAttributeBuilder.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import org.apache.commons.lang3.StringUtils; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; - -@PVPMETADATA -public class EIDIssuingNationAttributeBuilder implements IPVPAttributeBuilder { - - public String getName() { - return EID_ISSUING_NATION_NAME; - } - - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - String countryCode = authData.getCiticenCountryCode(); - if (StringUtils.isNotEmpty(countryCode)) - return g.buildStringAttribute(EID_ISSUING_NATION_FRIENDLY_NAME, - EID_ISSUING_NATION_NAME, countryCode); - - else - return null; - } - - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(EID_ISSUING_NATION_FRIENDLY_NAME, - EID_ISSUING_NATION_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSectorForIDAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSectorForIDAttributeBuilder.java deleted file mode 100644 index 39c9db8f..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSectorForIDAttributeBuilder.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import org.apache.commons.lang3.StringUtils; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; - -@PVPMETADATA -public class EIDSectorForIDAttributeBuilder implements IPVPAttributeBuilder { - - public String getName() { - return EID_SECTOR_FOR_IDENTIFIER_NAME; - } - - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - String bpktype = authData.getBPKType(); - - if (StringUtils.isEmpty(authData.getBPKType())) - throw new UnavailableAttributeException(EID_SECTOR_FOR_IDENTIFIER_NAME); - - return g.buildStringAttribute(EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, - EID_SECTOR_FOR_IDENTIFIER_NAME, bpktype); - } - - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, - EID_SECTOR_FOR_IDENTIFIER_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSignerCertificate.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSignerCertificate.java deleted file mode 100644 index bab521b4..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSignerCertificate.java +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * Copyright 2019 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.Base64Utils; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; - -@PVPMETADATA -public class EIDSignerCertificate implements IPVPAttributeBuilder { - private static final Logger log = LoggerFactory.getLogger(EIDSignerCertificate.class); - - @Override - public String getName() { - return EID_SIGNER_CERTIFICATE_NAME; - } - - @Override - public <ATT> ATT build(final ISPConfiguration oaParam, final IAuthData authData, - final IAttributeGenerator<ATT> g) throws AttributeBuilderException { - - if (authData instanceof IEidAuthData) { - try { - - final byte[] signerCertificate = ((IEidAuthData)authData).getSignerCertificate(); - if (signerCertificate != null) { - return g.buildStringAttribute(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME, EID_SIGNER_CERTIFICATE_NAME, - Base64Utils.encodeToString(signerCertificate)); - - } else - log.info(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME + " is only available in MOA-ID context"); - - } catch (final Exception e) { - log.info("Signer certificate BASE64 encoding error"); - - } - - } else - log.info(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME + " is only available in AuthHandler context"); - - - throw new UnavailableAttributeException(EID_SIGNER_CERTIFICATE_NAME); - - } - - @Override - public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME, EID_SIGNER_CERTIFICATE_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSourcePIN.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSourcePIN.java deleted file mode 100644 index 4db2d87d..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSourcePIN.java +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import org.apache.commons.lang3.StringUtils; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -import at.gv.egiz.eaaf.core.exceptions.AttributePolicyException; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; - -@Deprecated -@PVPMETADATA -public class EIDSourcePIN implements IPVPAttributeBuilder { - - public String getName() { - return EID_SOURCE_PIN_NAME; - } - - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - - if (authData.isBaseIDTransferRestrication()) - throw new AttributePolicyException(EID_SOURCE_PIN_NAME); - - else { - if (StringUtils.isEmpty(authData.getIdentificationValue())) - throw new UnavailableAttributeException(EID_SOURCE_PIN_NAME); - - return g.buildStringAttribute(EID_SOURCE_PIN_FRIENDLY_NAME, EID_SOURCE_PIN_NAME, authData.getIdentificationValue()); - } - } - - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(EID_SOURCE_PIN_FRIENDLY_NAME, EID_SOURCE_PIN_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSourcePINType.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSourcePINType.java deleted file mode 100644 index 42e47a42..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDSourcePINType.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; - -@Deprecated -@PVPMETADATA -public class EIDSourcePINType implements IPVPAttributeBuilder { - - public String getName() { - return EID_SOURCE_PIN_TYPE_NAME; - } - - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - - if (authData.isBaseIDTransferRestrication()) - throw new UnavailableAttributeException(EID_SOURCE_PIN_TYPE_NAME); - - else { - return g.buildStringAttribute(EID_SOURCE_PIN_TYPE_FRIENDLY_NAME, EID_SOURCE_PIN_TYPE_NAME, authData.getIdentificationType()); - } - } - - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(EID_SOURCE_PIN_TYPE_FRIENDLY_NAME, EID_SOURCE_PIN_TYPE_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDeIDASQAALevelAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDeIDASQAALevelAttributeBuilder.java deleted file mode 100644 index 1e7b323b..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EIDeIDASQAALevelAttributeBuilder.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; - -@PVPMETADATA -public class EIDeIDASQAALevelAttributeBuilder implements IPVPAttributeBuilder { - - public String getName() { - return EID_CITIZEN_EIDAS_QAA_LEVEL_NAME; - } - - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - - return g.buildStringAttribute(EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, - EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, authData.getEIDASQAALevel()); - } - - - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, - EID_CITIZEN_EIDAS_QAA_LEVEL_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidCcsUrl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidCcsUrl.java new file mode 100644 index 00000000..27b78059 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidCcsUrl.java @@ -0,0 +1,45 @@ +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; + +@PvpMetadata +public class EidCcsUrl implements IPvpAttributeBuilder { + private static final Logger log = LoggerFactory.getLogger(EID_CCS_URL_NAME); + + @Override + public String getName() { + return EID_CCS_URL_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + if (authData instanceof IEidAuthData) { + final String bkuurl = ((IEidAuthData) authData).getVdaEndPointUrl(); + if (StringUtils.isNotEmpty(bkuurl)) { + return g.buildStringAttribute(EID_CCS_URL_FRIENDLY_NAME, EID_CCS_URL_NAME, bkuurl); + } + + } else { + log.info(EID_CCS_URL_FRIENDLY_NAME + " is only available in MOA-ID context"); + } + + throw new UnavailableAttributeException(EID_CCS_URL_NAME); + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(EID_CCS_URL_FRIENDLY_NAME, EID_CCS_URL_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEidTokenBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEidTokenBuilder.java new file mode 100644 index 00000000..be208e8e --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEidTokenBuilder.java @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Base64Utils; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; + +@PvpMetadata +public class EidEidTokenBuilder implements IPvpAttributeBuilder { + private static final Logger log = LoggerFactory.getLogger(EidEidTokenBuilder.class); + + @Override + public String getName() { + return EID_E_ID_TOKEN_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + + if (authData instanceof IEidAuthData) { + if (((IEidAuthData) authData).getEidToken() == null) { + throw new UnavailableAttributeException(EID_E_ID_TOKEN_NAME); + } + + return g.buildStringAttribute(EID_E_ID_TOKEN_FRIENDLY_NAME, EID_E_ID_TOKEN_NAME, + Base64Utils.encodeToString(((IEidAuthData) authData).getEidToken())); + } else { + log.info(EID_E_ID_TOKEN_FRIENDLY_NAME + " is only available in AuthHandler context"); + } + + throw new UnavailableAttributeException(EID_E_ID_TOKEN_NAME); + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(EID_E_ID_TOKEN_FRIENDLY_NAME, EID_E_ID_TOKEN_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEidasQaaLevelAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEidasQaaLevelAttributeBuilder.java new file mode 100644 index 00000000..7d0d6a95 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEidasQaaLevelAttributeBuilder.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +@PvpMetadata +public class EidEidasQaaLevelAttributeBuilder implements IPvpAttributeBuilder { + + @Override + public String getName() { + return EID_CITIZEN_EIDAS_QAA_LEVEL_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + + return g.buildStringAttribute(EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, + EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, authData.getEidasQaaLevel()); + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, + EID_CITIZEN_EIDAS_QAA_LEVEL_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEncryptedSourceIdAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEncryptedSourceIdAttributeBuilder.java new file mode 100644 index 00000000..246f585c --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEncryptedSourceIdAttributeBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright 2019 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +public class EidEncryptedSourceIdAttributeBuilder + implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) + throws AttributeBuilderException { + return g.buildStringAttribute(getFriendlyName(), getName(), authData.getEncryptedSourceId()); + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(getFriendlyName(), getName()); + + } + + @Override + public String getName() { + return EID_ENCRYPTED_SOURCEID_NAME; + } + + private String getFriendlyName() { + return EID_ENCRYPTED_SOURCEID_FRIENDLY_NAME; + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEncryptedSourceIdTypeAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEncryptedSourceIdTypeAttributeBuilder.java new file mode 100644 index 00000000..3ffa6a14 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEncryptedSourceIdTypeAttributeBuilder.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +public class EidEncryptedSourceIdTypeAttributeBuilder + implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) + throws AttributeBuilderException { + return g.buildStringAttribute(getFriendlyName(), getName(), + authData.getEncryptedSourceIdType()); + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(getFriendlyName(), getName()); + + } + + @Override + public String getName() { + return EID_ENCRYPTED_SOURCEID_TYPE_NAME; + } + + private String getFriendlyName() { + return EID_ENCRYPTED_SOURCEID_TYPE_FRIENDLY_NAME; + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityLinkBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityLinkBuilder.java new file mode 100644 index 00000000..b7249786 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityLinkBuilder.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Base64Utils; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; + +@Deprecated +@PvpMetadata +public class EidIdentityLinkBuilder implements IPvpAttributeBuilder { + private static final Logger log = LoggerFactory.getLogger(EidIdentityLinkBuilder.class); + + @Override + public String getName() { + return EID_IDENTITY_LINK_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + try { + String ilAssertion = null; + if (authData.getIdentityLink() == null) { + throw new UnavailableAttributeException(EID_IDENTITY_LINK_NAME); + } + + ilAssertion = authData.getIdentityLink().getSerializedSamlAssertion(); + + return g.buildStringAttribute(EID_IDENTITY_LINK_FRIENDLY_NAME, EID_IDENTITY_LINK_NAME, + Base64Utils.encodeToString(ilAssertion.getBytes("UTF-8"))); + + } catch (final IOException e) { + log.warn("IdentityLink serialization error.", e); + return g.buildEmptyAttribute(EID_IDENTITY_LINK_FRIENDLY_NAME, EID_IDENTITY_LINK_NAME); + } + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(EID_IDENTITY_LINK_FRIENDLY_NAME, EID_IDENTITY_LINK_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityStatusLevelAttributeBuiler.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityStatusLevelAttributeBuiler.java index 6a8de559..ee51564e 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityStatusLevelAttributeBuiler.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIdentityStatusLevelAttributeBuiler.java @@ -6,42 +6,45 @@ import org.slf4j.LoggerFactory; import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; import at.gv.egiz.eaaf.core.api.idp.IAuthData; import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; -@PVPMETADATA -public class EidIdentityStatusLevelAttributeBuiler implements IPVPAttributeBuilder { - private static final Logger log = LoggerFactory.getLogger(EidIdentityStatusLevelAttributeBuiler.class); - - @Override - public String getName() { - return EID_IDENTITY_STATUS_LEVEL_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, IAttributeGenerator<ATT> g) - throws AttributeBuilderException { - - if (authData instanceof IEidAuthData) { - if (((IEidAuthData)authData).getEIDStatus() == null) - throw new UnavailableAttributeException(getName()); - - return g.buildStringAttribute(getFriendlyName(), - getName(), ((IEidAuthData)authData).getEIDStatus().getURI()); - } else - log.info(getFriendlyName() + " is only available in EAAF context"); - - throw new UnavailableAttributeException(getName()); - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(getFriendlyName(), getName()); - } - - private String getFriendlyName() { - return EID_IDENTITY_STATUS_LEVEL_FRIENDLY_NAME; - } +@PvpMetadata +public class EidIdentityStatusLevelAttributeBuiler implements IPvpAttributeBuilder { + private static final Logger log = + LoggerFactory.getLogger(EidIdentityStatusLevelAttributeBuiler.class); + + @Override + public String getName() { + return EID_IDENTITY_STATUS_LEVEL_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + + if (authData instanceof IEidAuthData) { + if (((IEidAuthData) authData).getEidStatus() == null) { + throw new UnavailableAttributeException(getName()); + } + + return g.buildStringAttribute(getFriendlyName(), getName(), + ((IEidAuthData) authData).getEidStatus().getUri()); + } else { + log.info(getFriendlyName() + " is only available in EAAF context"); + } + + throw new UnavailableAttributeException(getName()); + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(getFriendlyName(), getName()); + } + + private String getFriendlyName() { + return EID_IDENTITY_STATUS_LEVEL_FRIENDLY_NAME; + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIssuingNationAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIssuingNationAttributeBuilder.java new file mode 100644 index 00000000..fd85871c --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIssuingNationAttributeBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +@PvpMetadata +public class EidIssuingNationAttributeBuilder implements IPvpAttributeBuilder { + + @Override + public String getName() { + return EID_ISSUING_NATION_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + final String countryCode = authData.getCiticenCountryCode(); + if (StringUtils.isNotEmpty(countryCode)) { + return g.buildStringAttribute(EID_ISSUING_NATION_FRIENDLY_NAME, EID_ISSUING_NATION_NAME, + countryCode); + } else { + return null; + } + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(EID_ISSUING_NATION_FRIENDLY_NAME, EID_ISSUING_NATION_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSectorForIdAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSectorForIdAttributeBuilder.java new file mode 100644 index 00000000..3aedf9ab --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSectorForIdAttributeBuilder.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; + +@PvpMetadata +public class EidSectorForIdAttributeBuilder implements IPvpAttributeBuilder { + + @Override + public String getName() { + return EID_SECTOR_FOR_IDENTIFIER_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + final String bpktype = authData.getBpkType(); + + if (StringUtils.isEmpty(authData.getBpkType())) { + throw new UnavailableAttributeException(EID_SECTOR_FOR_IDENTIFIER_NAME); + } + + return g.buildStringAttribute(EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, + EID_SECTOR_FOR_IDENTIFIER_NAME, bpktype); + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, + EID_SECTOR_FOR_IDENTIFIER_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSignerCertificate.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSignerCertificate.java new file mode 100644 index 00000000..6f857779 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSignerCertificate.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Base64Utils; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; + +@PvpMetadata +public class EidSignerCertificate implements IPvpAttributeBuilder { + private static final Logger log = LoggerFactory.getLogger(EidSignerCertificate.class); + + @Override + public String getName() { + return EID_SIGNER_CERTIFICATE_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + + if (authData instanceof IEidAuthData) { + try { + + final byte[] signerCertificate = ((IEidAuthData) authData).getSignerCertificate(); + if (signerCertificate != null) { + return g.buildStringAttribute(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME, + EID_SIGNER_CERTIFICATE_NAME, Base64Utils.encodeToString(signerCertificate)); + + } else { + log.info(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME + " is only available in MOA-ID context"); + } + + } catch (final Exception e) { + log.info("Signer certificate BASE64 encoding error"); + + } + + } else { + log.info(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME + " is only available in AuthHandler context"); + } + + throw new UnavailableAttributeException(EID_SIGNER_CERTIFICATE_NAME); + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(EID_SIGNER_CERTIFICATE_FRIENDLY_NAME, EID_SIGNER_CERTIFICATE_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSourcePin.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSourcePin.java new file mode 100644 index 00000000..591c176e --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSourcePin.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.AttributePolicyException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; + +@Deprecated +@PvpMetadata +public class EidSourcePin implements IPvpAttributeBuilder { + + @Override + public String getName() { + return EID_SOURCE_PIN_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + + if (authData.isBaseIdTransferRestrication()) { + throw new AttributePolicyException(EID_SOURCE_PIN_NAME); + } else { + if (StringUtils.isEmpty(authData.getIdentificationValue())) { + throw new UnavailableAttributeException(EID_SOURCE_PIN_NAME); + } + + return g.buildStringAttribute(EID_SOURCE_PIN_FRIENDLY_NAME, EID_SOURCE_PIN_NAME, + authData.getIdentificationValue()); + } + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(EID_SOURCE_PIN_FRIENDLY_NAME, EID_SOURCE_PIN_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSourcePinType.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSourcePinType.java new file mode 100644 index 00000000..4fba8d0a --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSourcePinType.java @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; + +@Deprecated +@PvpMetadata +public class EidSourcePinType implements IPvpAttributeBuilder { + + @Override + public String getName() { + return EID_SOURCE_PIN_TYPE_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + + if (authData.isBaseIdTransferRestrication()) { + throw new UnavailableAttributeException(EID_SOURCE_PIN_TYPE_NAME); + } else { + return g.buildStringAttribute(EID_SOURCE_PIN_TYPE_FRIENDLY_NAME, EID_SOURCE_PIN_TYPE_NAME, + authData.getIdentificationType()); + } + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(EID_SOURCE_PIN_TYPE_FRIENDLY_NAME, EID_SOURCE_PIN_TYPE_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/GivenNameAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/GivenNameAttributeBuilder.java index 87512b03..46e22468 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/GivenNameAttributeBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/GivenNameAttributeBuilder.java @@ -1,60 +1,55 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ + package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; import org.apache.commons.lang3.StringUtils; import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; -@PVPMETADATA -public class GivenNameAttributeBuilder implements IPVPAttributeBuilder { - - @Override - public String getName() { - return GIVEN_NAME_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - if (StringUtils.isNotEmpty(authData.getGivenName())) - return g.buildStringAttribute(GIVEN_NAME_FRIENDLY_NAME, GIVEN_NAME_NAME, authData.getGivenName()); - else - throw new UnavailableAttributeException(GIVEN_NAME_NAME); - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(GIVEN_NAME_FRIENDLY_NAME, GIVEN_NAME_NAME); - } +@PvpMetadata +public class GivenNameAttributeBuilder implements IPvpAttributeBuilder { + + @Override + public String getName() { + return GIVEN_NAME_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + if (StringUtils.isNotEmpty(authData.getGivenName())) { + return g.buildStringAttribute(GIVEN_NAME_FRIENDLY_NAME, GIVEN_NAME_NAME, + authData.getGivenName()); + } else { + throw new UnavailableAttributeException(GIVEN_NAME_NAME); + } + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(GIVEN_NAME_FRIENDLY_NAME, GIVEN_NAME_NAME); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PVPMETADATA.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PVPMETADATA.java deleted file mode 100644 index 81ad2126..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PVPMETADATA.java +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import java.lang.annotation.Retention; - -@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) -public @interface PVPMETADATA { - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PVPVersionAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PVPVersionAttributeBuilder.java deleted file mode 100644 index 38377641..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PVPVersionAttributeBuilder.java +++ /dev/null @@ -1,51 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; - -@PVPMETADATA -public class PVPVersionAttributeBuilder implements IPVPAttributeBuilder { - - public String getName() { - return PVP_VERSION_NAME; - } - - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - return g.buildStringAttribute(PVP_VERSION_FRIENDLY_NAME, PVP_VERSION_NAME, PVP_VERSION_2_1); - } - - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(PVP_VERSION_FRIENDLY_NAME, PVP_VERSION_NAME); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PrincipalNameAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PrincipalNameAttributeBuilder.java index d753550e..67451a07 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PrincipalNameAttributeBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PrincipalNameAttributeBuilder.java @@ -1,60 +1,55 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; import org.apache.commons.lang3.StringUtils; import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IPVPAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; -@PVPMETADATA -public class PrincipalNameAttributeBuilder implements IPVPAttributeBuilder { - - @Override - public String getName() { - return PRINCIPAL_NAME_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, - IAttributeGenerator<ATT> g) throws AttributeBuilderException { - if (StringUtils.isNotEmpty(authData.getFamilyName())) - return g.buildStringAttribute(PRINCIPAL_NAME_FRIENDLY_NAME, PRINCIPAL_NAME_NAME, authData.getFamilyName()); - else - throw new UnavailableAttributeException(PRINCIPAL_NAME_NAME); - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(PRINCIPAL_NAME_FRIENDLY_NAME, PRINCIPAL_NAME_NAME); - } - +@PvpMetadata +public class PrincipalNameAttributeBuilder implements IPvpAttributeBuilder { + + @Override + public String getName() { + return PRINCIPAL_NAME_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + if (StringUtils.isNotEmpty(authData.getFamilyName())) { + return g.buildStringAttribute(PRINCIPAL_NAME_FRIENDLY_NAME, PRINCIPAL_NAME_NAME, + authData.getFamilyName()); + } else { + throw new UnavailableAttributeException(PRINCIPAL_NAME_NAME); + } + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(PRINCIPAL_NAME_FRIENDLY_NAME, PRINCIPAL_NAME_NAME); + } + } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PvpMetadata.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PvpMetadata.java new file mode 100644 index 00000000..6d1c40f9 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PvpMetadata.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import java.lang.annotation.Retention; + +@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) +public @interface PvpMetadata { + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PvpVersionAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PvpVersionAttributeBuilder.java new file mode 100644 index 00000000..204f1c45 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/PvpVersionAttributeBuilder.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +@PvpMetadata +public class PvpVersionAttributeBuilder implements IPvpAttributeBuilder { + + @Override + public String getName() { + return PVP_VERSION_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + return g.buildStringAttribute(PVP_VERSION_FRIENDLY_NAME, PVP_VERSION_NAME, PVP_VERSION_2_1); + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(PVP_VERSION_FRIENDLY_NAME, PVP_VERSION_NAME); + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPCountryCodeAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPCountryCodeAttributeBuilder.java deleted file mode 100644 index 9a365eb3..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPCountryCodeAttributeBuilder.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import at.gv.egiz.eaaf.core.api.data.ExtendedPVPAttributeDefinitions; -import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; - -public class SPCountryCodeAttributeBuilder implements IAttributeBuilder, ExtendedPVPAttributeDefinitions { - - @Override - public String getName() { - return SP_COUNTRYCODE_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, IAttributeGenerator<ATT> g) - throws AttributeBuilderException { - //this attribute can not generated yet - return null; -// return g.buildStringAttribute( -// SP_COUNTRYCODE_FRIENDLY_NAME, -// SP_COUNTRYCODE_NAME, -// oaParam.getFriendlyName()); - - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(SP_COUNTRYCODE_FRIENDLY_NAME, SP_COUNTRYCODE_NAME); - - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPFriendlyNameAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPFriendlyNameAttributeBuilder.java deleted file mode 100644 index 2062f35b..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPFriendlyNameAttributeBuilder.java +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import at.gv.egiz.eaaf.core.api.data.ExtendedPVPAttributeDefinitions; -import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; - -public class SPFriendlyNameAttributeBuilder implements IAttributeBuilder, ExtendedPVPAttributeDefinitions { - - @Override - public String getName() { - return SP_FRIENDLYNAME_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, IAttributeGenerator<ATT> g) - throws AttributeBuilderException { - return g.buildStringAttribute( - SP_FRIENDLYNAME_FRIENDLY_NAME, - SP_FRIENDLYNAME_NAME, - oaParam.getFriendlyName()); - - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(SP_FRIENDLYNAME_FRIENDLY_NAME, SP_FRIENDLYNAME_NAME); - - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPUniqueIdAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPUniqueIdAttributeBuilder.java deleted file mode 100644 index bac2ec24..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPUniqueIdAttributeBuilder.java +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import at.gv.egiz.eaaf.core.api.data.ExtendedPVPAttributeDefinitions; -import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; - -public class SPUniqueIdAttributeBuilder implements IAttributeBuilder, ExtendedPVPAttributeDefinitions { - - @Override - public String getName() { - return SP_UNIQUEID_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, IAttributeGenerator<ATT> g) - throws AttributeBuilderException { - return g.buildStringAttribute( - SP_UNIQUEID_FRIENDLY_NAME, - SP_UNIQUEID_NAME, - oaParam.getUniqueIdentifier()); - - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(SP_UNIQUEID_FRIENDLY_NAME, SP_UNIQUEID_NAME); - - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPUsesMandates.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPUsesMandates.java deleted file mode 100644 index 7ad6cb09..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SPUsesMandates.java +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; - -import at.gv.egiz.eaaf.core.api.data.ExtendedPVPAttributeDefinitions; -import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; - -public class SPUsesMandates implements IAttributeBuilder, ExtendedPVPAttributeDefinitions { - - @Override - public String getName() { - return SP_USESMANDATES_NAME; - } - - @Override - public <ATT> ATT build(ISPConfiguration oaParam, IAuthData authData, IAttributeGenerator<ATT> g) - throws AttributeBuilderException { - //this attribute can not generated yet - return null; - - } - - @Override - public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) { - return g.buildEmptyAttribute(SP_USESMANDATES_FRIENDLY_NAME, SP_USESMANDATES_NAME); - - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpCountryCodeAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpCountryCodeAttributeBuilder.java new file mode 100644 index 00000000..fe05b28d --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpCountryCodeAttributeBuilder.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +public class SpCountryCodeAttributeBuilder + implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + + @Override + public String getName() { + return SP_COUNTRYCODE_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) + throws AttributeBuilderException { + // this attribute can not generated yet + return null; + // return g.buildStringAttribute( + // SP_COUNTRYCODE_FRIENDLY_NAME, + // SP_COUNTRYCODE_NAME, + // oaParam.getFriendlyName()); + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(SP_COUNTRYCODE_FRIENDLY_NAME, SP_COUNTRYCODE_NAME); + + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpFriendlyNameAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpFriendlyNameAttributeBuilder.java new file mode 100644 index 00000000..37102fc5 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpFriendlyNameAttributeBuilder.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +public class SpFriendlyNameAttributeBuilder + implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + + @Override + public String getName() { + return SP_FRIENDLYNAME_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) + throws AttributeBuilderException { + return g.buildStringAttribute(SP_FRIENDLYNAME_FRIENDLY_NAME, SP_FRIENDLYNAME_NAME, + oaParam.getFriendlyName()); + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(SP_FRIENDLYNAME_FRIENDLY_NAME, SP_FRIENDLYNAME_NAME); + + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUniqueIdAttributeBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUniqueIdAttributeBuilder.java new file mode 100644 index 00000000..760dbbe5 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUniqueIdAttributeBuilder.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +public class SpUniqueIdAttributeBuilder + implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + + @Override + public String getName() { + return SP_UNIQUEID_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) + throws AttributeBuilderException { + return g.buildStringAttribute(SP_UNIQUEID_FRIENDLY_NAME, SP_UNIQUEID_NAME, + oaParam.getUniqueIdentifier()); + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(SP_UNIQUEID_FRIENDLY_NAME, SP_UNIQUEID_NAME); + + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUsesMandates.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUsesMandates.java new file mode 100644 index 00000000..44ff4e50 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUsesMandates.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; + +public class SpUsesMandates implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + + @Override + public String getName() { + return SP_USESMANDATES_NAME; + } + + @Override + public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator<ATT> g) + throws AttributeBuilderException { + // this attribute can not generated yet + return null; + + } + + @Override + public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { + return g.buildEmptyAttribute(SP_USESMANDATES_FRIENDLY_NAME, SP_USESMANDATES_NAME); + + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/AbstractConfigurationImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/AbstractConfigurationImpl.java index 55662326..d279446b 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/AbstractConfigurationImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/AbstractConfigurationImpl.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.conf; import java.io.File; @@ -40,195 +33,199 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egiz.eaaf.core.api.idp.IExtendedConfiguration; -import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; public abstract class AbstractConfigurationImpl implements IExtendedConfiguration { - private static final Logger log = LoggerFactory.getLogger(AbstractConfigurationImpl.class); - - private static final String URI_SCHEME_CLASSPATH = "classpath"; - private static final String URI_SCHEME_FILESYSTEM = "file"; - - private final URI internalConfigPath; - private final URI configRootDirectory; - private final Properties properties; - - public AbstractConfigurationImpl(final String configPath) throws EAAFConfigurationException { - InputStream is = null; - try { - log.debug("Starting EAAFCore initialization process .... "); - - if (StringUtils.isEmpty(configPath)) { - log.debug("Primary configuration is empty. Search for backup configuration .... "); - final String backupConfigPath = getBackupConfigPath(); - if (StringUtils.isEmpty(backupConfigPath)) { - log.error("No configuration file found."); - throw new EAAFConfigurationException("config.01", null); - - } - - internalConfigPath = new URI(getBackupConfigPath()); - - } else - internalConfigPath = new URI(configPath); - - log.info("Load EAAFCore configuration from " + internalConfigPath); - - - //extract configuration root directory - //TODO: check if it works with classpath - final File propertiesFile = new File(internalConfigPath); - if (!propertiesFile.exists()) { - log.error("Configuration file: " + internalConfigPath + " is NOT found on filesystem"); - throw new EAAFConfigurationException("config.18", null); - - } - - final String configDir = propertiesFile.getParent(); - configRootDirectory = new File(configDir).toURI(); - log.debug("Set EAAFCore configuration root directory to " + configRootDirectory.toString()); - - - //get input stream from configuration path - if (internalConfigPath.getScheme().equals(URI_SCHEME_FILESYSTEM)) { - log.trace("Load config from filesystem"); - is = new FileInputStream(propertiesFile); - - } else if (internalConfigPath.getScheme().equals(URI_SCHEME_CLASSPATH)) { - log.trace("Load config from classpath"); - is = this.getClass().getResourceAsStream(internalConfigPath.toString()); - - } else { - log.error("Can not load EAAFCore configuration. Unsupported prefix! (Only 'file:' and 'classpath:') "); - throw new EAAFConfigurationException("config.24", new Object[] {internalConfigPath, "'file:'"}); - - } - - if (is == null) { - log.error("Can NOT load EAAFCore configuration from file " + internalConfigPath.toString()); - throw new EAAFConfigurationException("config.03", - new Object[] {internalConfigPath.toString()}); - - } - - - //load EAAF core configuration into properties object - properties = new Properties(); - properties.load(is); - - log.info("EAAFCore configuration loaded"); - - } catch (URISyntaxException | IOException e) { - log.error("Can not parse configuration path " + configPath + " or " + getBackupConfigPath()); - throw new EAAFConfigurationException("config.03", new Object[]{configPath + " or " + getBackupConfigPath()}, e); - - } finally { - if (is != null) { - try { - is.close(); - - } catch (final IOException e) { - log.warn("Can not close inputstream from configuration loader!"); - - } - } - } - - } - - @Override - public String getBasicConfiguration(String key) { - if (StringUtils.isNotEmpty(key)) { - final String value = properties.getProperty(addPrefixToKey(key)); - if (value != null) - return value.trim(); - } - - return null; - } - - @Override - public String getBasicConfiguration(String key, String defaultValue) { - if (StringUtils.isNotEmpty(key)) { - final String value = properties.getProperty(addPrefixToKey(key), defaultValue); - if (value != null) - return value.trim(); - } - - return defaultValue; - } - - - @Override - public Boolean getBasicConfigurationBoolean(String key) { - final String value = getBasicConfiguration(key); - if (value != null) - return Boolean.parseBoolean(value); - else - return null; - - } - - - @Override - public boolean getBasicConfigurationBoolean(String key, boolean defaultValue) { - final Boolean result = getBasicConfigurationBoolean(key); - if (result != null) - return result; - else - return defaultValue; - - } - - @Override - public Map<String, String> getBasicConfigurationWithPrefix(String prefix) { - return KeyValueUtils.getSubSetWithPrefix(KeyValueUtils.convertPropertiesToMap(properties), addPrefixToKey(prefix)); - - } - - @Override - public Properties getFullConfigurationProperties() { - return properties; - - } - - @Override - public URI getConfigurationRootDirectory() { - return configRootDirectory; - - } - - @Override - public URI getConfigurationFilePath() { - return internalConfigPath; - - } - - /** - * Get the path to backup configuration - * - * @return A filepath file: or a classpath classpath: - */ - abstract protected String getBackupConfigPath(); - - /** - * Get a specific configuration-key prefix for this software implementation - * - * @return - */ - abstract public String getApplicationSpecificKeyPrefix(); - - - private String addPrefixToKey(String key) { - if (StringUtils.isNotEmpty(getApplicationSpecificKeyPrefix())) { - if (getApplicationSpecificKeyPrefix().endsWith(KeyValueUtils.KEY_DELIMITER)) - return getApplicationSpecificKeyPrefix() + key; - else - return getApplicationSpecificKeyPrefix() + KeyValueUtils.KEY_DELIMITER + key; - - } - - return key; - - } + private static final Logger log = LoggerFactory.getLogger(AbstractConfigurationImpl.class); + + private static final String URI_SCHEME_CLASSPATH = "classpath"; + private static final String URI_SCHEME_FILESYSTEM = "file"; + + private final URI internalConfigPath; + private final URI configRootDirectory; + private final Properties properties; + + /** + * Basic configuration loader implementation. + * + * @param configPath Path to configuration + * @throws EaafConfigurationException In case of a configuration error + */ + public AbstractConfigurationImpl(final String configPath) throws EaafConfigurationException { + InputStream is = null; + try { + log.debug("Starting EAAFCore initialization process .... "); + + if (StringUtils.isEmpty(configPath)) { + log.debug("Primary configuration is empty. Search for backup configuration .... "); + final String backupConfigPath = getBackupConfigPath(); + if (StringUtils.isEmpty(backupConfigPath)) { + log.error("No configuration file found."); + throw new EaafConfigurationException("config.01", null); + + } + + internalConfigPath = new URI(getBackupConfigPath()); + + } else { + internalConfigPath = new URI(configPath); + } + + log.info("Load EAAFCore configuration from " + internalConfigPath); + + // extract configuration root directory + // TODO: check if it works with classpath + final File propertiesFile = new File(internalConfigPath); + if (!propertiesFile.exists()) { + log.error("Configuration file: " + internalConfigPath + " is NOT found on filesystem"); + throw new EaafConfigurationException("config.18", null); + + } + + final String configDir = propertiesFile.getParent(); + configRootDirectory = new File(configDir).toURI(); + log.debug("Set EAAFCore configuration root directory to " + configRootDirectory.toString()); + + // get input stream from configuration path + if (internalConfigPath.getScheme().equals(URI_SCHEME_FILESYSTEM)) { + log.trace("Load config from filesystem"); + is = new FileInputStream(propertiesFile); + + } else if (internalConfigPath.getScheme().equals(URI_SCHEME_CLASSPATH)) { + log.trace("Load config from classpath"); + is = this.getClass().getResourceAsStream(internalConfigPath.toString()); + + } else { + log.error( + "Can not load EAAFCore configuration. Unsupported prefix! (Only 'file:' and 'classpath:') "); + throw new EaafConfigurationException("config.24", new Object[] { internalConfigPath, "'file:'" }); + + } + + if (is == null) { + log.error("Can NOT load EAAFCore configuration from file " + internalConfigPath.toString()); + throw new EaafConfigurationException("config.03", new Object[] { internalConfigPath.toString() }); + + } + + // load EAAF core configuration into properties object + properties = new Properties(); + properties.load(is); + + log.info("EAAFCore configuration loaded"); + + } catch (URISyntaxException | IOException e) { + log.error("Can not parse configuration path " + configPath + " or " + getBackupConfigPath()); + throw new EaafConfigurationException("config.03", new Object[] { configPath + " or " + + getBackupConfigPath() }, + e); + + } finally { + if (is != null) { + try { + is.close(); + + } catch (final IOException e) { + log.warn("Can not close inputstream from configuration loader!"); + + } + } + } + + } + + @Override + public String getBasicConfiguration(final String key) { + if (StringUtils.isNotEmpty(key)) { + final String value = properties.getProperty(addPrefixToKey(key)); + if (value != null) { + return value.trim(); + } + } + + return null; + } + + @Override + public String getBasicConfiguration(final String key, final String defaultValue) { + if (StringUtils.isNotEmpty(key)) { + final String value = properties.getProperty(addPrefixToKey(key), defaultValue); + if (value != null) { + return value.trim(); + } + } + + return defaultValue; + } + + @Override + public boolean getBasicConfigurationBoolean(final String key) { + return getBasicConfigurationBoolean(key, false); + + } + + @Override + public boolean getBasicConfigurationBoolean(final String key, final boolean defaultValue) { + final String value = getBasicConfiguration(key); + if (value != null) { + return Boolean.parseBoolean(value); + } else { + return defaultValue; + } + + } + + @Override + public Map<String, String> getBasicConfigurationWithPrefix(final String prefix) { + return KeyValueUtils.getSubSetWithPrefix(KeyValueUtils.convertPropertiesToMap(properties), addPrefixToKey( + prefix)); + + } + + @Override + public Properties getFullConfigurationProperties() { + return properties; + + } + + @Override + public URI getConfigurationRootDirectory() { + return configRootDirectory; + + } + + @Override + public URI getConfigurationFilePath() { + return internalConfigPath; + + } + + /** + * Get the path to backup configuration. + * + * @return A filepath file: or a classpath classpath: + */ + protected abstract String getBackupConfigPath(); + + /** + * Get a specific configuration-key prefix for this software implementation. + * + * @return + */ + public abstract String getApplicationSpecificKeyPrefix(); + + private String addPrefixToKey(final String key) { + if (StringUtils.isNotEmpty(getApplicationSpecificKeyPrefix())) { + if (getApplicationSpecificKeyPrefix().endsWith(KeyValueUtils.KEY_DELIMITER)) { + return getApplicationSpecificKeyPrefix() + key; + } else { + return getApplicationSpecificKeyPrefix() + KeyValueUtils.KEY_DELIMITER + key; + } + + } + + return key; + + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/AbstractSpringBootConfigurationImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/AbstractSpringBootConfigurationImpl.java index dd13b534..5dcbcb7e 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/AbstractSpringBootConfigurationImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/AbstractSpringBootConfigurationImpl.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.conf; import java.net.URI; @@ -35,6 +28,10 @@ import java.util.Map.Entry; import javax.annotation.PostConstruct; +import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; + import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,175 +42,168 @@ import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.Environment; import org.springframework.core.env.PropertySource; -import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; -import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; -import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; - public abstract class AbstractSpringBootConfigurationImpl implements IConfigurationWithSP { - private static final Logger log = LoggerFactory.getLogger(AbstractSpringBootConfigurationImpl.class); - - @Autowired private Environment env; - - public static final String PROP_CONFIG_ROOT_DIR = "core.configRootDir"; - - @PostConstruct - private void initialize() throws EAAFConfigurationException { - if (getConfigurationRootDirectory() == null) { - throw new EAAFConfigurationException("config.08", new Object[] {addPrefixToKey(PROP_CONFIG_ROOT_DIR)}); - - } - - } - - @Override - public String getBasicConfiguration(String key) { - if (StringUtils.isNotEmpty(key)) { - final String value = env.getProperty(addPrefixToKey(key)); - if (value != null) - return value.trim(); - } - - return null; - } - - @Override - public String getBasicConfiguration(String key, String defaultValue) { - if (StringUtils.isNotEmpty(key)) { - final String value = env.getProperty(addPrefixToKey(key), defaultValue); - if (value != null) - return value.trim(); - } - - return defaultValue; - } - - @Override - public Map<String, String> getBasicConfigurationWithPrefix(String prefix) { - final Map<String, String> configProps = getPropertiesStartingWith((ConfigurableEnvironment) env, addPrefixToKey(prefix)); - return KeyValueUtils.removePrefixFromKeys(configProps, addPrefixToKey(prefix) + "."); - - - } - - @Override - public Boolean getBasicConfigurationBoolean(String key) { - final String value = getBasicConfiguration(key); - if (StringUtils.isNotEmpty(value)) - return Boolean.valueOf(value.trim()); - else - return null; - } - - @Override - public boolean getBasicConfigurationBoolean(String key, boolean defaultValue) { - final Boolean value = getBasicConfigurationBoolean(key); - if (value != null) - return value; - else - return defaultValue; - } - - @Override - public URI getConfigurationRootDirectory() { - try { - return new URI(env.getRequiredProperty(addPrefixToKey(PROP_CONFIG_ROOT_DIR))); - - } catch (IllegalStateException | URISyntaxException e) { - log.warn("ConfigRootDirectory is NOT set"); - return null; - - } - - } - - - /** - * Get the path to backup configuration - * - * @return A filepath file: or a classpath classpath: - */ - abstract protected String getBackupConfigPath(); - - /** - * Get a specific configuration-key prefix for this software implementation - * - * @return - */ - abstract public String getApplicationSpecificKeyPrefix(); - - - private String addPrefixToKey(String key) { - if (StringUtils.isNotEmpty(getApplicationSpecificKeyPrefix())) { - if (getApplicationSpecificKeyPrefix().endsWith(KeyValueUtils.KEY_DELIMITER)) - return getApplicationSpecificKeyPrefix() + key; - else - return getApplicationSpecificKeyPrefix() + KeyValueUtils.KEY_DELIMITER + key; - - } - - return key; - - } - - private static Map<String, String> getPropertiesStartingWith( ConfigurableEnvironment aEnv, String aKeyPrefix ) { - final Map<String,String> result = new HashMap<>(); - final Map<String,Object> map = getAllProperties(aEnv); - - for (final Entry<String, Object> entry : map.entrySet()) { - final String key = entry.getKey(); - - if ( key.startsWith( aKeyPrefix ) ) - { - result.put( key, (String) entry.getValue() ); - } - } - - return result; - } - - private static Map<String,Object> getAllProperties( ConfigurableEnvironment aEnv ) { - final Map<String,Object> result = new HashMap<>(); - aEnv.getPropertySources().forEach( ps -> addAll( result, getAllProperties( ps ) ) ); - return result; - - } - - private static Map<String,Object> getAllProperties( PropertySource<?> aPropSource ) { - final Map<String,Object> result = new HashMap<>(); - - if ( aPropSource instanceof CompositePropertySource) - { - final CompositePropertySource cps = (CompositePropertySource) aPropSource; - cps.getPropertySources().forEach( ps -> addAll( result, getAllProperties( ps ) ) ); - return result; - } - - if ( aPropSource instanceof EnumerablePropertySource<?> ) - { - final EnumerablePropertySource<?> ps = (EnumerablePropertySource<?>) aPropSource; - Arrays.asList( ps.getPropertyNames() ).forEach( key -> result.put( key, ps.getProperty( key ) ) ); - return result; - } - - // note: Most descendants of PropertySource are EnumerablePropertySource. There are some - // few others like JndiPropertySource or StubPropertySource - log.debug( "Given PropertySource is instanceof " + aPropSource.getClass().getName() - + " and cannot be iterated" ); - - return result; - - } - - private static void addAll( Map<String, Object> aBase, Map<String, Object> aToBeAdded ) - { - for (final Entry<String, Object> entry : aToBeAdded.entrySet()) - { - if ( aBase.containsKey( entry.getKey() ) ) - { - continue; - } - - aBase.put( entry.getKey(), entry.getValue() ); - } - } + private static final Logger log = LoggerFactory.getLogger(AbstractSpringBootConfigurationImpl.class); + + @Autowired + private Environment env; + + public static final String PROP_CONFIG_ROOT_DIR = "core.configRootDir"; + + @PostConstruct + private void initialize() throws EaafConfigurationException { + if (getConfigurationRootDirectory() == null) { + throw new EaafConfigurationException("config.08", new Object[] { addPrefixToKey( + PROP_CONFIG_ROOT_DIR) }); + + } + + } + + @Override + public String getBasicConfiguration(final String key) { + if (StringUtils.isNotEmpty(key)) { + final String value = env.getProperty(addPrefixToKey(key)); + if (value != null) { + return value.trim(); + } + } + + return null; + } + + @Override + public String getBasicConfiguration(final String key, final String defaultValue) { + if (StringUtils.isNotEmpty(key)) { + final String value = env.getProperty(addPrefixToKey(key), defaultValue); + if (value != null) { + return value.trim(); + } + } + + return defaultValue; + } + + @Override + public Map<String, String> getBasicConfigurationWithPrefix(final String prefix) { + final Map<String, String> configProps = getPropertiesStartingWith((ConfigurableEnvironment) env, + addPrefixToKey(prefix)); + return KeyValueUtils.removePrefixFromKeys(configProps, addPrefixToKey(prefix) + "."); + + } + + @Override + public boolean getBasicConfigurationBoolean(final String key) { + return getBasicConfigurationBoolean(key, false); + + } + + @Override + public boolean getBasicConfigurationBoolean(final String key, final boolean defaultValue) { + final String value = getBasicConfiguration(key); + if (StringUtils.isNotEmpty(value)) { + return Boolean.valueOf(value.trim()); + } else { + return defaultValue; + } + } + + @Override + public URI getConfigurationRootDirectory() { + try { + return new URI(env.getRequiredProperty(addPrefixToKey(PROP_CONFIG_ROOT_DIR))); + + } catch (IllegalStateException | URISyntaxException e) { + log.warn("ConfigRootDirectory is NOT set"); + return null; + + } + + } + + /** + * Get the path to backup configuration. + * + * @return A filepath file: or a classpath classpath: + */ + protected abstract String getBackupConfigPath(); + + /** + * Get a specific configuration-key prefix for this software implementation. + * + * @return + */ + public abstract String getApplicationSpecificKeyPrefix(); + + private String addPrefixToKey(final String key) { + if (StringUtils.isNotEmpty(getApplicationSpecificKeyPrefix())) { + if (getApplicationSpecificKeyPrefix().endsWith(KeyValueUtils.KEY_DELIMITER)) { + return getApplicationSpecificKeyPrefix() + key; + } else { + return getApplicationSpecificKeyPrefix() + KeyValueUtils.KEY_DELIMITER + key; + } + + } + + return key; + + } + + private static Map<String, String> getPropertiesStartingWith(final ConfigurableEnvironment aenv, + final String akeyPrefix) { + final Map<String, String> result = new HashMap<>(); + final Map<String, Object> map = getAllProperties(aenv); + + for (final Entry<String, Object> entry : map.entrySet()) { + final String key = entry.getKey(); + + if (key.startsWith(akeyPrefix)) { + result.put(key, (String) entry.getValue()); + } + } + + return result; + } + + private static Map<String, Object> getAllProperties(final ConfigurableEnvironment aenv) { + final Map<String, Object> result = new HashMap<>(); + aenv.getPropertySources().forEach(ps -> addAll(result, getAllProperties(ps))); + return result; + + } + + private static Map<String, Object> getAllProperties(final PropertySource<?> apropSource) { + final Map<String, Object> result = new HashMap<>(); + + if (apropSource instanceof CompositePropertySource) { + final CompositePropertySource cps = (CompositePropertySource) apropSource; + cps.getPropertySources().forEach(ps -> addAll(result, getAllProperties(ps))); + return result; + } + + if (apropSource instanceof EnumerablePropertySource<?>) { + final EnumerablePropertySource<?> ps = (EnumerablePropertySource<?>) apropSource; + Arrays.asList(ps.getPropertyNames()).forEach(key -> result.put(key, ps.getProperty(key))); + return result; + } + + // note: Most descendants of PropertySource are EnumerablePropertySource. There + // are some + // few others like JndiPropertySource or StubPropertySource + log.trace("Given PropertySource is instanceof " + apropSource.getClass().getName() + + " and cannot be iterated"); + + return result; + + } + + private static void addAll(final Map<String, Object> abase, final Map<String, Object> atoBeAdded) { + for (final Entry<String, Object> entry : atoBeAdded.entrySet()) { + if (abase.containsKey(entry.getKey())) { + continue; + } + + abase.put(entry.getKey(), entry.getValue()); + } + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/SPConfigurationImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/SPConfigurationImpl.java deleted file mode 100644 index 1b99ce50..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/SPConfigurationImpl.java +++ /dev/null @@ -1,191 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.conf; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.api.data.EAAFConfigConstants; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; - -public class SPConfigurationImpl implements ISPConfiguration { - private static final long serialVersionUID = 688541755446463453L; - - private static final Logger log = LoggerFactory.getLogger(SPConfigurationImpl.class); - - private final Map<String, String> spConfiguration; - private final List<String> targetAreasWithNoInteralBaseIdRestriction; - private final List<String> targetAreasWithNoBaseIdTransmissionRestriction; - - public SPConfigurationImpl(final Map<String, String> spConfig, IConfiguration authConfig) { - this.spConfiguration = spConfig; - - //set oa specific restrictions - targetAreasWithNoInteralBaseIdRestriction = Collections.unmodifiableList( - KeyValueUtils.getListOfCSVValues( - authConfig.getBasicConfiguration( - CONFIG_KEY_RESTRICTIONS_BASEID_INTERNAL, - EAAFConstants.URN_PREFIX_CDID))); - - targetAreasWithNoBaseIdTransmissionRestriction = Collections.unmodifiableList( - KeyValueUtils.getListOfCSVValues( - authConfig.getBasicConfiguration( - CONFIG_KEY_RESTRICTIONS_BASEID_TRANSMISSION, - EAAFConstants.URN_PREFIX_CDID))); - - if (log.isTraceEnabled()) { - log.trace("Internal policy for OA: " + getUniqueIdentifier()); - for (String el : targetAreasWithNoInteralBaseIdRestriction) - log.trace(" Allow baseID processing for prefix " + el); - for (String el : targetAreasWithNoBaseIdTransmissionRestriction) - log.trace(" Allow baseID transfer for prefix " + el); - - } - } - - - @Override - public final Map<String, String> getFullConfiguration() { - return this.spConfiguration; - - } - - @Override - public final String getConfigurationValue(String key) { - if (key == null) - return null; - else - return this.spConfiguration.get(key); - - } - - @Override - public final String getConfigurationValue(String key, String defaultValue) { - String value = getConfigurationValue(key); - if (value == null) - return defaultValue; - else - return value; - } - - - @Override - public final Boolean isConfigurationValue(String key) { - String value = getConfigurationValue(key); - if (value != null) { - return Boolean.parseBoolean(value); - - } - - return null; - } - - - @Override - public final boolean isConfigurationValue(String key, boolean defaultValue) { - String value = getConfigurationValue(key); - if (value != null) { - return Boolean.parseBoolean(value); - - } - - return defaultValue; - } - - @Override - public final boolean containsConfigurationKey(String key) { - if (key == null) - return false; - else - return this.spConfiguration.containsKey(key); - - } - - @Override - public String getUniqueIdentifier() { - return getConfigurationValue(EAAFConfigConstants.SERVICE_UNIQUEIDENTIFIER); - - } - - @Override - public boolean hasBaseIdInternalProcessingRestriction() { - return false; - - } - - @Override - public boolean hasBaseIdTransferRestriction() { - return true; - - } - - - @Override - public final List<String> getTargetsWithNoBaseIdInternalProcessingRestriction() { - return this.targetAreasWithNoInteralBaseIdRestriction; - } - - - @Override - public final List<String> getTargetsWithNoBaseIdTransferRestriction() { - return this.targetAreasWithNoBaseIdTransmissionRestriction; - } - - - @Override - public List<String> getRequiredLoA() { - log.warn("Method not implemented: " + SPConfigurationImpl.class.getName() + " 'getRequiredLoA()'"); - return null; - } - - @Override - public String getLoAMatchingMode() { - log.warn("Method not implemented: " + SPConfigurationImpl.class.getName() + " 'getLoAMatchingMode()'"); - return null; - } - - @Override - public String getAreaSpecificTargetIdentifier() { - log.warn("Method not implemented: " + SPConfigurationImpl.class.getName() + " 'getAreaSpecificTargetIdentifier()'"); - return null; - } - - - @Override - public String getFriendlyName() { - log.warn("Method not implemented: " + SPConfigurationImpl.class.getName() + " 'getFriendlyName()'"); - return null; - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java index 4505163d..dd113907 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java @@ -1,211 +1,268 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.controller; import java.io.IOException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.text.StringEscapeUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.web.bind.annotation.ExceptionHandler; - import at.gv.egiz.components.eventlog.api.EventConstants; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IStatusMessenger; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; import at.gv.egiz.eaaf.core.api.data.ExceptionContainer; import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService; import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.utils.Random; import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.web.bind.annotation.ExceptionHandler; /** + * Basic application controller that implements core error-handling. + * * @author tlenz * */ public abstract class AbstractController { - private static final Logger log = LoggerFactory.getLogger(AbstractController.class); - - @Autowired(required=true) protected IProtocolAuthenticationService protAuthService; - @Autowired(required=true) protected ApplicationContext applicationContext; - @Autowired(required=true) protected IConfigurationWithSP authConfig; - @Autowired(required=true) protected ITransactionStorage transactionStorage; - @Autowired(required=true) protected IStatusMessenger statusMessager; - - @Autowired protected IRevisionLogger revisionsLogger; - - @ExceptionHandler({EAAFException.class}) - public void EAAFExceptionHandler(final HttpServletRequest req, final HttpServletResponse resp, final Exception e) throws IOException { - try { - protAuthService.handleErrorNoRedirect(e, req, resp, true); - - } catch (final EAAFException e1) { - log.warn("Can NOT handle an 'EAAFException'. Forwarding to generic error ... ", e); - IOExceptionHandler(resp, e); - - } - - } - - @ExceptionHandler({Exception.class}) - public void GenericExceptionHandler(final HttpServletResponse resp, final Exception exception) throws IOException { - log.error("Internel Server Error." , exception); - resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); - resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error!" + - "(Errorcode=9199" - +" | Description=" - + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(exception.getMessage())) - + ")"); - return; - - } - - @ExceptionHandler({IOException.class}) - public void IOExceptionHandler(final HttpServletResponse resp, final Throwable exception) { - log.error("Internel Server Error." , exception); - resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - return; - - } - - protected void handleError(final String errorMessage, final Throwable exceptionThrown, - final HttpServletRequest req, final HttpServletResponse resp, IRequest pendingReq) throws IOException, EAAFException { - - Throwable loggedException = null; - final Throwable extractedException = extractOriginalExceptionFromProcessException(exceptionThrown); - - //extract pendingRequestID and originalException if it was a TaskExecutionException - if (extractedException instanceof TaskExecutionException) { - //set original exception - loggedException = ((TaskExecutionException) extractedException).getOriginalException(); - - } else if (exceptionThrown instanceof PendingReqIdValidationException) { - log.trace("Find pendingRequestId validation exception. Looking for invalid pending-request ... "); - if (((PendingReqIdValidationException) exceptionThrown).getInvalidPendingReq() != null) - pendingReq = ((PendingReqIdValidationException) exceptionThrown).getInvalidPendingReq(); - - } - - //use TaskExecutionException directly, if no Original Exeception is included - if (loggedException == null) - loggedException = exceptionThrown; - - try { - //switch to protocol-finalize method to generate a protocol-specific error message - - //log error directly in debug mode - if (log.isDebugEnabled()) - log.warn(loggedException.getMessage(), loggedException); - - - //put exception into transaction store for redirect - final String key = Random.nextLongRandom(); - if (pendingReq != null) { - revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR); - transactionStorage.put(key, - new ExceptionContainer(pendingReq, loggedException), -1); - - } else { - transactionStorage.put(key, - new ExceptionContainer(null, loggedException), -1); - - } - - //build up redirect URL - String redirectURL = null; - redirectURL = ServletUtils.getBaseUrl(req); - redirectURL += "/"+ProtocolFinalizationController.ENDPOINT_ERRORHANDLING - + "?" + EAAFConstants.PARAM_HTTP_ERROR_CODE + "=" + key; - - resp.setContentType("text/html"); - resp.setStatus(302); - - resp.addHeader("Location", redirectURL); - log.debug("REDIRECT TO: " + redirectURL); - - return; - - } catch (final Exception e) { - log.warn("Default error-handling FAILED. Exception can not be stored ....", e); - log.info("Switch to generic generic backup error-handling ... "); - protAuthService.handleErrorNoRedirect(loggedException, req, resp, true); - - } - - } - - - - - - /** - * Extracts a TaskExecutionException of a ProcessExecutionExeception Stacktrace. - * - * @param exception - * @return Return the latest TaskExecutionExecption if exists, otherwise the latest ProcessExecutionException - */ - private Throwable extractOriginalExceptionFromProcessException(final Throwable exception) { - Throwable exholder = exception; - TaskExecutionException taskExc = null; - - while(exholder != null - && exholder instanceof ProcessExecutionException) { - final ProcessExecutionException procExc = (ProcessExecutionException) exholder; - if (procExc.getCause() != null && - procExc.getCause() instanceof TaskExecutionException) { - taskExc = (TaskExecutionException) procExc.getCause(); - exholder = taskExc.getOriginalException(); - - } else - break; - - } - - if (taskExc == null) - return exholder; - - else - return taskExc; - } - - - + private static final Logger log = LoggerFactory.getLogger(AbstractController.class); + + @Autowired(required = true) + protected IProtocolAuthenticationService protAuthService; + @Autowired(required = true) + protected ApplicationContext applicationContext; + @Autowired(required = true) + protected IConfigurationWithSP authConfig; + @Autowired(required = true) + protected ITransactionStorage transactionStorage; + @Autowired(required = true) + protected IStatusMessenger statusMessager; + + @Autowired + protected IRevisionLogger revisionsLogger; + + /** + * EAAF framework exception handler. + * + * <p> + * This handler start a protocol-specific error handling. + * </p> + * + * @param req http request + * @param resp http response + * @param e exception + * @throws IOException in case of an exception handling error + */ + @ExceptionHandler({ EaafException.class }) + public void eaafExceptionHandler(final HttpServletRequest req, final HttpServletResponse resp, + final Exception e) throws IOException { + try { + protAuthService.handleErrorNoRedirect(e, req, resp, true); + + } catch (final EaafException e1) { + log.warn("Can NOT handle an 'EAAFException'. Forwarding to generic error ... ", e); + ioExceptionHandler(resp, e); + + } + + } + + /** + * Generic exception handler. + * + * <p> + * This handler wrote an internal server error into http response + * </p> + * + * @param resp http response + * @param exception exception + * @throws IOException In case of an internal error. + */ + @ExceptionHandler({ Exception.class }) + public void genericExceptionHandler(final HttpServletResponse resp, final Exception exception) + throws IOException { + log.error("Internel Server Error.", exception); + resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error!" + + "(Errorcode=9199" + " | Description=" + + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(exception.getMessage())) + + ")"); + + } + + /** + * Generic exception handler. + * + * <p> + * This handler wrote an internal server error into http response + * </p> + * + * @param resp http response + * @param exception exception + */ + @ExceptionHandler({ IOException.class }) + public void ioExceptionHandler(final HttpServletResponse resp, final Throwable exception) { + log.error("Internel Server Error.", exception); + resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + + } + + protected void handleError(final String errorMessage, final Throwable exceptionThrown, + final HttpServletRequest req, final HttpServletResponse resp, IRequest pendingReq) + throws IOException, EaafException { + + final Pair<IRequest, Throwable> errorToHandle = + exractExceptionThatShouldBeLogged(pendingReq, exceptionThrown); + + try { + final String errorKey = storeErrorAndGetErrorToken(errorToHandle); + + // build up redirect URL + final String redirectUrl = generateErrorRedirectUrl(req, errorKey); + resp.setContentType("text/html"); + resp.setStatus(302); + + resp.addHeader("Location", redirectUrl); + log.debug("REDIRECT TO: " + redirectUrl); + + return; + + } catch (final Exception e) { + log.warn("Default error-handling FAILED. Exception can not be stored ....", e); + log.info("Switch to generic generic backup error-handling ... "); + protAuthService.handleErrorNoRedirect(errorToHandle.getSecond(), req, resp, true); + + } + + } + + protected String generateErrorRedirectUrl(final HttpServletRequest req, String errorKey) { + String redirectUrl = null; + redirectUrl = ServletUtils.getBaseUrl(req); + redirectUrl += "/" + ProtocolFinalizationController.ENDPOINT_ERRORHANDLING + "?" + + EaafConstants.PARAM_HTTP_ERROR_CODE + "=" + errorKey; + return redirectUrl; + + } + + protected String storeErrorAndGetErrorToken(Pair<IRequest, Throwable> errorToHandle) throws EaafException { + // log error directly in debug mode + if (log.isDebugEnabled()) { + log.warn(errorToHandle.getSecond().getMessage(), errorToHandle.getSecond()); + } + + // put exception into transaction store for redirect + final String errorKey = Random.nextLongRandom(); + if (errorToHandle.getFirst() != null) { + revisionsLogger.logEvent(errorToHandle.getFirst(), EventConstants.TRANSACTION_ERROR); + transactionStorage.put(errorKey, new ExceptionContainer(errorToHandle.getFirst(), errorToHandle + .getSecond()), -1); + + } else { + transactionStorage.put(errorKey, new ExceptionContainer(null, errorToHandle.getSecond()), -1); + + } + + return errorKey; + + } + + @Nonnull + protected Pair<IRequest, Throwable> exractExceptionThatShouldBeLogged( + @Nullable IRequest pendingReq, @Nonnull Throwable exceptionThrown) { + Throwable loggedException = null; + final Throwable extractedException = + extractOriginalExceptionFromProcessException(exceptionThrown); + + // extract pendingRequestID and originalException if it was a + // TaskExecutionException + if (extractedException instanceof TaskExecutionException) { + // set original exception + loggedException = ((TaskExecutionException) extractedException).getOriginalException(); + + } else if (exceptionThrown instanceof PendingReqIdValidationException) { + log.trace( + "Find pendingRequestId validation exception. Looking for invalid pending-request ... "); + + if (((PendingReqIdValidationException) exceptionThrown).getInvalidPendingReq() != null) { + pendingReq = ((PendingReqIdValidationException) exceptionThrown).getInvalidPendingReq(); + + } + + } + + // use TaskExecutionException directly, if no Original Exeception is included + if (loggedException == null) { + loggedException = exceptionThrown; + + } + + return Pair.newInstance(pendingReq, loggedException); + + } + + /** + * Extracts a TaskExecutionException of a ProcessExecutionExeception Stacktrace. + * + * @param exception error + * @return Return the latest TaskExecutionExecption if exists, otherwise the + * latest ProcessExecutionException + */ + private Throwable extractOriginalExceptionFromProcessException(final Throwable exception) { + Throwable exholder = exception; + TaskExecutionException taskExc = null; + + while (exholder != null && exholder instanceof ProcessExecutionException) { + final ProcessExecutionException procExc = (ProcessExecutionException) exholder; + if (procExc.getCause() != null && procExc.getCause() instanceof TaskExecutionException) { + taskExc = (TaskExecutionException) procExc.getCause(); + exholder = taskExc.getOriginalException(); + + } else { + break; + } + + } + + if (taskExc == null) { + return exholder; + } else { + return taskExc; + } + } + } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java index b87c9b78..098bca4c 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.controller; import java.io.IOException; @@ -39,81 +32,85 @@ import org.springframework.beans.factory.annotation.Autowired; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IRequestStorage; import at.gv.egiz.eaaf.core.api.IStatusMessenger; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.exceptions.EAAFIllegalStateException; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafIllegalStateException; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; /** * Servlet that resumes a suspended process (in case of asynchronous tasks). - * + * * @author tknall - * + * */ public abstract class AbstractProcessEngineSignalController extends AbstractController { - private static final Logger log = LoggerFactory.getLogger(AbstractProcessEngineSignalController.class); - - @Autowired(required=true) protected ProcessEngine processEngine; - @Autowired(required=true) protected IRequestStorage requestStorage; - - protected void signalProcessManagement(HttpServletRequest req, HttpServletResponse resp) throws IOException, EAAFException { - String pendingRequestID = StringEscapeUtils.escapeHtml4(getPendingRequestId(req)); - IRequest pendingReq = null; - try { - if (pendingRequestID == null) { - new EAAFException( - IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, - null); - - } - - pendingReq = requestStorage.getPendingRequest(pendingRequestID); - if (pendingReq == null) { - log.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure."); - throw new EAAFException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, new Object[]{pendingRequestID}); - - } - - //change pending-request ID - requestStorage.changePendingRequestID(pendingReq); - pendingRequestID = pendingReq.getPendingRequestId(); - - // process instance is mandatory - if (pendingReq.getProcessInstanceId() == null) { - throw new EAAFIllegalStateException(new Object[]{"MOA session does not provide process instance id."}); - - } - - // wake up next task - processEngine.signal(pendingReq); - - } catch (Exception ex) { - handleError(null, ex, req, resp, pendingReq); - - } finally { - //MOASessionDBUtils.closeSession(); - TransactionIDUtils.removeAllLoggingVariables(); - - } - - - } - - /** - * Retrieves the current pending-request id from the HttpServletRequest parameter - * - * <p/> - * Note that this class/method can be overwritten by modules providing their own strategy of retrieving the - * respective pending-request id. - * - * @param request - * The unterlying HttpServletRequest. - * @return The current pending-request id. - */ - public String getPendingRequestId(HttpServletRequest request) { - return StringEscapeUtils.escapeHtml4(request.getParameter(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID)); - - } + private static final Logger log = + LoggerFactory.getLogger(AbstractProcessEngineSignalController.class); + + @Autowired(required = true) + protected ProcessEngine processEngine; + @Autowired(required = true) + protected IRequestStorage requestStorage; + + protected void signalProcessManagement(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException, EaafException { + final String pendingRequestID = StringEscapeUtils.escapeHtml4(getPendingRequestId(req)); + IRequest pendingReq = null; + try { + if (pendingRequestID == null) { + throw new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null); + + } + + pendingReq = requestStorage.getPendingRequest(pendingRequestID); + if (pendingReq == null) { + log.info("No PendingRequest with Id: " + pendingRequestID + + " Maybe, a transaction timeout occure."); + throw new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, + new Object[] { pendingRequestID }); + + } + + // change pending-request ID + requestStorage.changePendingRequestID(pendingReq); + + // process instance is mandatory + if (pendingReq.getProcessInstanceId() == null) { + throw new EaafIllegalStateException( + new Object[] { "MOA session does not provide process instance id." }); + + } + + // wake up next task + processEngine.signal(pendingReq); + + } catch (final Exception ex) { + handleError(null, ex, req, resp, pendingReq); + + } finally { + // MOASessionDBUtils.closeSession(); + TransactionIdUtils.removeAllLoggingVariables(); + + } + + } + + /** + * Retrieves the current pending-request id from the HttpServletRequest + * parameter + * + * <p/> + * Note that this class/method can be overwritten by modules providing their own + * strategy of retrieving the respective pending-request id. + * + * @param request The unterlying HttpServletRequest. + * @return The current pending-request id. + */ + public String getPendingRequestId(final HttpServletRequest request) { + return StringEscapeUtils + .escapeHtml4(request.getParameter(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID)); + + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java index b830e240..51a8aefd 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java @@ -1,25 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.controller; import java.io.IOException; @@ -39,110 +36,125 @@ import at.gv.egiz.components.eventlog.api.EventConstants; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IRequestStorage; import at.gv.egiz.eaaf.core.api.IStatusMessenger; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; import at.gv.egiz.eaaf.core.api.data.ExceptionContainer; -import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; /** + * Protocol finialization end-point. + * * @author tlenz * */ @Controller public class ProtocolFinalizationController extends AbstractController { - private static final Logger log = LoggerFactory.getLogger(ProtocolFinalizationController.class); - public static final String ENDPOINT_FINALIZEPROTOCOL = "finalizeAuthProtocol"; - public static final String ENDPOINT_ERRORHANDLING = "errorHandling"; - - @Autowired(required=true) IRequestStorage requestStorage; - - @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = {RequestMethod.GET}) - public void errorHandling(HttpServletRequest req, HttpServletResponse resp) throws EAAFException, IOException { - //receive an authentication error - String errorid = StringEscapeUtils.escapeHtml4(req.getParameter(EAAFConstants.PARAM_HTTP_ERROR_CODE)); - if (errorid != null) { - IRequest pendingReq = null; - try { - //load stored exception from database - ExceptionContainer container = transactionStorage.get(errorid, ExceptionContainer.class); - if (container != null) { - //remove exception if it was found - transactionStorage.remove(errorid); - - Throwable throwable = container.getExceptionThrown(); - pendingReq = container.getPendingRequest(); - - if (pendingReq != null) { - //build protocol-specific error message if possible - protAuthService.buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq); - - //remove active user-session - transactionStorage.remove(pendingReq.getPendingRequestId()); - - return; - - } else { - protAuthService.handleErrorNoRedirect(throwable, req, resp, true); - - } - } else { - protAuthService.handleErrorNoRedirect( - new EAAFException( - IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, - null), req, resp, false); - - } - - } catch (Throwable e) { - log.error(e.getMessage(), e); - protAuthService.handleErrorNoRedirect(e, req, resp, false); - - } finally { - //remove pending-request - if (pendingReq != null) { - requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); - revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); - - } - - } - - } else { - log.debug("Request contains NO ErrorId"); - protAuthService.handleErrorNoRedirect( - new EAAFException( - IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, - null), req, resp, false); - - } - - } - - - @RequestMapping(value = ENDPOINT_FINALIZEPROTOCOL, method = {RequestMethod.GET}) - public void finalizeAuthProtocol(HttpServletRequest req, HttpServletResponse resp) throws EAAFException, IOException { - - //read pendingRequest from http request - Object idObject = StringEscapeUtils.escapeHtml4(req.getParameter(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID)); - IRequest pendingReq = null; - String pendingRequestID = null; - if (idObject != null && (idObject instanceof String)) { - pendingRequestID = (String) idObject; - pendingReq = requestStorage.getPendingRequest(pendingRequestID); - - } - - if (pendingReq == null) { - log.error("No PendingRequest with ID " + pendingRequestID + " found.!"); - protAuthService.handleErrorNoRedirect( - new EAAFException( - IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, - new Object[]{pendingRequestID, - }), req, resp, false); - - } else - protAuthService.finalizeAuthentication(req, resp, pendingReq); - - } - + private static final Logger log = LoggerFactory.getLogger(ProtocolFinalizationController.class); + public static final String ENDPOINT_FINALIZEPROTOCOL = "finalizeAuthProtocol"; + public static final String ENDPOINT_ERRORHANDLING = "errorHandling"; + + @Autowired(required = true) + IRequestStorage requestStorage; + + /** + * End-Point to handle errors. + * + * @param req http request + * @param resp http response + * @throws EaafException In case of an internal error + * @throws IOException In case of a servlet error + */ + @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = { RequestMethod.GET }) + public void errorHandling(final HttpServletRequest req, final HttpServletResponse resp) + throws EaafException, IOException { + // receive an authentication error + final String errorid = + StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE)); + if (errorid != null) { + IRequest pendingReq = null; + try { + // load stored exception from database + final ExceptionContainer container = + transactionStorage.get(errorid, ExceptionContainer.class); + if (container != null) { + // remove exception if it was found + transactionStorage.remove(errorid); + + final Throwable throwable = container.getExceptionThrown(); + pendingReq = container.getPendingRequest(); + + if (pendingReq != null) { + // build protocol-specific error message if possible + protAuthService.buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq); + + // remove active user-session + transactionStorage.remove(pendingReq.getPendingRequestId()); + + return; + + } else { + protAuthService.handleErrorNoRedirect(throwable, req, resp, true); + + } + } else { + protAuthService.handleErrorNoRedirect( + new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null), + req, resp, false); + + } + + } catch (final Throwable e) { + log.error(e.getMessage(), e); + protAuthService.handleErrorNoRedirect(e, req, resp, false); + + } finally { + // remove pending-request + if (pendingReq != null) { + requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, + pendingReq.getUniqueTransactionIdentifier()); + + } + + } + + } else { + log.debug("Request contains NO ErrorId"); + protAuthService.handleErrorNoRedirect( + new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null), req, + resp, false); + + } + + } + + /** + * End-Point to finalize authentication protocol. + * + * @param req http request + * @param resp http response + * @throws EaafException In case of an internal error + * @throws IOException In case of a servlet error + */ + @RequestMapping(value = ENDPOINT_FINALIZEPROTOCOL, method = { RequestMethod.GET }) + public void finalizeAuthProtocol(final HttpServletRequest req, final HttpServletResponse resp) + throws EaafException, IOException { + + // read pendingRequest from http request + final String pendingRequestID = StringEscapeUtils + .escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID)); + final IRequest pendingReq = requestStorage.getPendingRequest(pendingRequestID); + + if (pendingReq == null) { + log.error("No PendingRequest with ID " + pendingRequestID + " found.!"); + protAuthService.handleErrorNoRedirect( + new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, + new Object[] { pendingRequestID, }), + req, resp, false); + + } else { + protAuthService.finalizeAuthentication(req, resp, pendingReq); + } + + } + } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java index 722a9304..adc8774a 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.controller.protocols; import java.io.Serializable; @@ -36,443 +29,514 @@ import java.util.Map; import java.util.Map.Entry; import java.util.UUID; +import javax.annotation.Nonnull; import javax.servlet.http.HttpServletRequest; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; +import at.gv.egiz.eaaf.core.impl.utils.HttpUtils; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; + import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +public abstract class RequestImpl implements IRequest, Serializable { + + private static final Logger log = LoggerFactory.getLogger(RequestImpl.class); + + public static final String DATAID_REQUESTER_IP_ADDRESS = "reqestImpl_requesterIPAddr"; + + private static final String ERROR_CODE_INTERNAL_00 = "eaaf.core.00"; + + private static final long serialVersionUID = 1L; + + private String module = null; + private String action = null; + + private String pendingRequestId = null; + private String processInstanceId; + private String internalSsoSessionId; + + private String uniqueTransactionIdentifer; + private String uniqueSessionIdentifer; + private String uniquePiiTransactionIdentifier; + + private String requestedServiceProviderIdentifer; + private String idpAuthUrl = null; + + private ISpConfiguration spConfiguration = null; + + private boolean passiv = false; + private boolean force = false; + private boolean isAbortedByUser = false; + + // every request needs authentication by default + private boolean needAuthentication = true; + + // every request is not authenticated by default + private boolean isAuthenticated = false; + + // every request needs no SSO by default + private boolean needSso = false; + + private boolean needUserConsent = false; + + private final Map<String, Object> genericDataStorage = new HashMap<>(); + + /** + * Initialize this pendingRequest object. + * + * @param req {@link HttpServletRequest} + * @param authConfig {@link IConfiguration} + * @throws EaafException + * + */ + public final void initialize(final HttpServletRequest req, final IConfigurationWithSP authConfig) + throws EaafException { + initialize(req, authConfig, null, null); + + } + + /** + * Initialize this pendingRequest object. + * + * @param req {@link HttpServletRequest} + * @param authConfig {@link IConfiguration} + * @param transactionId Unique ID for technical log correlation that should be used in this pendingRequest + * @throws EaafException + * + */ + public final void initialize(final HttpServletRequest req, final IConfigurationWithSP authConfig, + @Nullable final String transactionId) throws EaafException { + initialize(req, authConfig, transactionId, null); + + } + + /** + * Initialize this pendingRequest object. + * + * @param req {@link HttpServletRequest} + * @param authConfig {@link IConfiguration} + * @param transactionId Unique ID for technical log correlation that should be used in this pendingRequest + * @param piiTransactionId Unique ID for PII data correlation that should be used in this pendingRequest + * for logging. If 'null' a new one will be generated + * + * @throws EaafException + * + */ + public final void initialize(@NonNull final HttpServletRequest req, + @NonNull final IConfigurationWithSP authConfig, @Nullable final String transactionId, + @Nullable final String piiTransactionId) + throws EaafException { + // use external transactionId or create new one if empty or null + if (StringUtils.isNotEmpty(transactionId)) { + uniqueTransactionIdentifer = transactionId; + } else { + uniqueTransactionIdentifer = UUID.randomUUID().toString(); + } + + // set unique transaction identifier for logging + TransactionIdUtils.setTransactionId(uniqueTransactionIdentifer); + + // use external piiTransactionId or create new one if empty or null + if (StringUtils.isNotEmpty(piiTransactionId)) { + uniquePiiTransactionIdentifier = piiTransactionId; + } else { + uniquePiiTransactionIdentifier = UUID.randomUUID().toString(); + } + + + // initialize session object + genericDataStorage.put(EaafConstants.AUTH_DATA_CREATED, new Date()); + // genericDataStorage.put(EAAFConstants.VALUE_SESSIONID, + // Random.nextLongRandom()); + + // check if End-Point is valid + final String authUrlString = HttpUtils.extractAuthUrlFromRequest(req); + URL authReqUrl; + try { + authReqUrl = new URL(authUrlString); + + } catch (final MalformedURLException e) { + log.error("IDP AuthenticationServiceURL Prefix is not a valid URL." + authUrlString, e); + throw new EaafAuthenticationException(ERROR_CODE_INTERNAL_00, new Object[] { authUrlString }, e); + + } + this.idpAuthUrl = authConfig.validateIdpUrl(authReqUrl); + if (this.idpAuthUrl == null) { + log.warn( + "Extract AuthenticationServiceURL: " + authReqUrl + " is NOT found in configuration."); + throw new EaafAuthenticationException(ERROR_CODE_INTERNAL_00, new Object[] { authUrlString }); + + } + + // set unique session identifier + final String uniqueID = (String) req.getAttribute(EaafConstants.UNIQUESESSIONIDENTIFIER); + if (StringUtils.isNotEmpty(uniqueID)) { + this.uniqueSessionIdentifer = uniqueID; + } else { + log.debug("Create new sessionIdentifier for this pendingRequest ... "); + this.uniqueSessionIdentifer = UUID.randomUUID().toString(); + + } + + // set requester's IP address + try { + setRawDataToTransaction(DATAID_REQUESTER_IP_ADDRESS, req.getRemoteAddr()); + + } catch (final EaafStorageException e) { + log.info("Can NOT store remote IP address into 'pendingRequest'.", e); + + } + + } + + public final void setSpEntityId(final String spIdentifier) { + this.requestedServiceProviderIdentifer = spIdentifier; + } + + @Override + public final String getSpEntityId() { + return this.requestedServiceProviderIdentifer; + } + + @Override + public final boolean isPassiv() { + return passiv; + } + + @Override + public final boolean forceAuth() { + return force; + } + + public final void setPassiv(final boolean passiv) { + this.passiv = passiv; + } + + public final void setForce(final boolean force) { + this.force = force; + } + + @Override + public final String requestedAction() { + return action; + } + + public final void setAction(final String action) { + this.action = action; + } + + @Override + public final String requestedModule() { + return module; + } + + public final void setModule(final String module) { + this.module = module; + } + + public final void setPendingRequestId(final String pendingReqId) { + this.pendingRequestId = pendingReqId; + + } + + @Override + @NonNull + public final String getPendingRequestId() { + if (pendingRequestId == null) { + throw new IllegalStateException("No PendingRequestId set!!!"); + } + + return pendingRequestId; + } + + @Override + public final String getInternalSsoSessionIdentifier() { + return this.internalSsoSessionId; + } + + @Override + public final void setInternalSsoSessionIdentifier(final String internalSsoSessionId) { + this.internalSsoSessionId = internalSsoSessionId; + + } + + @Override + @Nonnull + public final <T> T getSessionData(@Nonnull final Class<T> wrapper) { + Assert.notNull(wrapper, "Wrapper must NOT null"); + if (AuthProcessDataWrapper.class.isAssignableFrom(wrapper)) { + try { + return wrapper.getConstructor(Map.class).newInstance(this.genericDataStorage); + + } catch (NoSuchMethodException | SecurityException | InstantiationException + | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + log.error("Can NOT instance wrapper: " + wrapper.getName(), e); + + } + + } + + log.error("Can NOT wrap generic data into session data. " + "Reason: Wrapper " + + wrapper.getName() + " is NOT a valid wrapper"); + throw new RuntimeException("Can NOT wrap generic data into session data. " + "Reason: Wrapper " + + wrapper.getName() + " is NOT a valid wrapper"); + + } + + @Override + public final ISpConfiguration getServiceProviderConfiguration() { + return this.spConfiguration; + + } + + @Override + public <T> T getServiceProviderConfiguration(final Class<T> decorator) { + if (this.spConfiguration != null) { + if (decorator.isAssignableFrom(this.spConfiguration.getClass())) { + return (T) this.spConfiguration; + + } else { + log.error("Can not decorate SP configuration by '" + decorator.getName() + "'."); + } + throw new RuntimeException( + "Can not decorate SP configuration by '" + decorator.getName() + "'."); + + } + + return null; + + } + + public void setOnlineApplicationConfiguration(final ISpConfiguration spConfig) { + this.spConfiguration = spConfig; + + } + + @Override + public final String getUniqueTransactionIdentifier() { + return this.uniqueTransactionIdentifer; + + } + + @Override + public final String getUniqueSessionIdentifier() { + return this.uniqueSessionIdentifer; + + } + + @Override + public final String getUniquePiiTransactionIdentifier() { + return uniquePiiTransactionIdentifier; + } + + @Override + public final String getProcessInstanceId() { + return this.processInstanceId; + + } + + /** + * Set an unique transaction identifier to correlate technical logging + * in one single transaction. + * + * @param id Unique identifier + */ + public final void setUniqueTransactionIdentifier(final String id) { + this.uniqueTransactionIdentifer = id; + + } + + /** + * Set an unique session identifier to correlate technical logging over a set of transactions, + * like SSO as one example. + * + * @param id Unique identifier + */ + public final void setUniqueSessionIdentifier(final String id) { + this.uniqueSessionIdentifer = id; + + } + + /** + * Set an unique transaction identifier to correlate PII related data. + * + * <p>This identifier will be not used for technical logging.</p> + * + * @param id Unique identifier + */ + public void setUniquePiiTransactionIdentifier(String id) { + this.uniquePiiTransactionIdentifier = id; + + } + + + public void setProcessInstanceId(final String id) { + this.processInstanceId = id; + + } + + @Override + public final String getAuthUrl() { + return this.idpAuthUrl; + } + + @Override + public final String getAuthUrlWithOutSlash() { + if (this.idpAuthUrl.endsWith("/")) { + return this.idpAuthUrl.substring(0, this.idpAuthUrl.length() - 1); + } else { + return this.idpAuthUrl; + } + + } + + @Override + public final boolean isNeedAuthentication() { + return needAuthentication; + } + + public final void setNeedAuthentication(final boolean needAuthentication) { + this.needAuthentication = needAuthentication; + } + + @Override + public final boolean isAuthenticated() { + return isAuthenticated; + } + + @Override + public final void setAuthenticated(final boolean isAuthenticated) { + this.isAuthenticated = isAuthenticated; + } + + @Override + public final boolean needSingleSignOnFunctionality() { + return needSso; + } + + @Override + public final void setNeedSingleSignOnFunctionality(final boolean needSso) { + this.needSso = needSso; + + } + + @Override + public final boolean isNeedUserConsent() { + return this.needUserConsent; + + } + + @Override + public final void setNeedUserConsent(final boolean needConsent) { + this.needUserConsent = needConsent; + + } + + @Override + public final boolean isAbortedByUser() { + return this.isAbortedByUser; + } + + @Override + public final void setAbortedByUser(final boolean isAborted) { + this.isAbortedByUser = isAborted; + + } + + @Override + public final Object getRawData(final String key) { + if (StringUtils.isNotEmpty(key)) { + return genericDataStorage.get(key); + + } + + log.info("Can not load generic request-data with key='null'"); + return null; + } + + @Override + public final <T> T getRawData(final String key, final Class<T> clazz) { + if (StringUtils.isNotEmpty(key)) { + final Object data = genericDataStorage.get(key); + + if (data == null) { + return null; + } + + try { + @SuppressWarnings("unchecked") + final T test = (T) data; + return test; + + } catch (final Exception e) { + log.warn("Generic request-data object can not be casted to requested type", e); + return null; + + } + + } + + log.info("Can not load generic request-data with key='null'"); + return null; + + } + + @Override + public final void setRawDataToTransaction(final String key, final Object object) + throws EaafStorageException { + if (StringUtils.isEmpty(key)) { + log.info("Generic request-data can not be stored with a 'null' key"); + throw new EaafStorageException("Generic request-data can not be stored with a 'null' key", + null); + + } + + if (object != null && !Serializable.class.isInstance(object)) { + log.warn( + "Generic request-data can only store objects which implements the 'Seralizable' interface"); + throw new EaafStorageException( + "Generic request-data can only store objects which implements the 'Seralizable' interface", + null); + } + + if (genericDataStorage.containsKey(key)) { + log.trace("Overwrite generic request-data with key:" + key); + } else { + log.trace("Add generic request-data with key:" + key + " to session."); + } + + genericDataStorage.put(key, object); + + } + + @Override + public final void setRawDataToTransaction(final Map<String, Object> map) + throws EaafStorageException { + if (map == null) { + log.info("Generic request-data can not be stored with a 'null' map"); + throw new EaafStorageException("Generic request-data can not be stored with a 'null' map", + null); + + } + + // validate and store values + for (final Entry<String, Object> el : map.entrySet()) { + setRawDataToTransaction(el.getKey(), el.getValue()); + } + + } -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; -import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; -import at.gv.egiz.eaaf.core.impl.utils.HTTPUtils; -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; - -public abstract class RequestImpl implements IRequest, Serializable{ - - private static final Logger log = LoggerFactory.getLogger(RequestImpl.class); - - public static final String DATAID_REQUESTER_IP_ADDRESS = "reqestImpl_requesterIPAddr"; - - private static final long serialVersionUID = 1L; - - private String module = null; - private String action = null; - - private String pendingRequestId = null; - private String processInstanceId; - private String internalSSOSessionId; - - private String uniqueTransactionIdentifer; - private String uniqueSessionIdentifer; - - private String requestedServiceProviderIdentifer; - private String idpAuthURL = null; - - private ISPConfiguration spConfiguration = null; - - private boolean passiv = false; - private boolean force = false; - private boolean isAbortedByUser = false; - - //every request needs authentication by default - private boolean needAuthentication = true; - - //every request is not authenticated by default - private boolean isAuthenticated = false; - - //every request needs no SSO by default - private boolean needSSO = false; - - private boolean needUserConsent = false; - - private final Map<String, Object> genericDataStorage = new HashMap<String, Object>(); - - - /** - * Initialize this pendingRequest object - * - * @param req {@link HttpServletRequest} - * @param authConfig {@link IConfiguration} - * @throws EAAFException - * - */ - public final void initialize(HttpServletRequest req, IConfigurationWithSP authConfig) throws EAAFException { - initialize(req, authConfig, null); - - } - - /** - * Initialize this pendingRequest object - * - * @param req {@link HttpServletRequest} - * @param authConfig {@link IConfiguration} - * @param transactionId transactionId that should be used in this pendingRequest for logging. If 'null' a new one will be generated - * - * @throws EAAFException - * - */ - public final void initialize(@NonNull HttpServletRequest req, @NonNull IConfigurationWithSP authConfig, @Nullable String transactionId) throws EAAFException { - //use external transactionId or create new one if empty or null - if (StringUtils.isNotEmpty(transactionId)) - uniqueTransactionIdentifer = transactionId; - else - uniqueTransactionIdentifer = Random.nextLongRandom(); - - //set unique transaction identifier for logging - TransactionIDUtils.setTransactionId(uniqueTransactionIdentifer); - - //initialize session object - genericDataStorage.put(EAAFConstants.AUTH_DATA_CREATED, new Date()); - //genericDataStorage.put(EAAFConstants.VALUE_SESSIONID, Random.nextLongRandom()); - - //check if End-Point is valid - final String authURLString = HTTPUtils.extractAuthURLFromRequest(req); - URL authReqURL; - try { - authReqURL = new URL(authURLString); - - } catch (final MalformedURLException e) { - log.error("IDP AuthenticationServiceURL Prefix is not a valid URL." + authURLString, e); - throw new EAAFAuthenticationException("errorId", new Object[]{authURLString}, e); - - } - this.idpAuthURL = authConfig.validateIDPURL(authReqURL); - if (this.idpAuthURL == null) { - log.warn("Extract AuthenticationServiceURL: " + authReqURL + " is NOT found in configuration."); - throw new EAAFAuthenticationException("errorId", new Object[]{authURLString}); - - } - - //set unique session identifier - final String uniqueID = (String) req.getAttribute(EAAFConstants.UNIQUESESSIONIDENTIFIER); - if (StringUtils.isNotEmpty(uniqueID)) - this.uniqueSessionIdentifer = uniqueID; - - else { - log.debug("Create new sessionIdentifier for this pendingRequest ... "); - this.uniqueSessionIdentifer = UUID.randomUUID().toString(); - - } - - //set requester's IP address - try { - setRawDataToTransaction(DATAID_REQUESTER_IP_ADDRESS, req.getRemoteAddr()); - - } catch (final EAAFStorageException e) { - log.info("Can NOT store remote IP address into 'pendingRequest'." , e); - - } - - } - - public final void setSPEntityId(String spIdentifier) { - this.requestedServiceProviderIdentifer = spIdentifier; - } - - @Override - public final String getSPEntityId() { - return this.requestedServiceProviderIdentifer; - } - - @Override - public final boolean isPassiv() { - return passiv; - } - - @Override - public final boolean forceAuth() { - return force; - } - - public final void setPassiv(boolean passiv) { - this.passiv = passiv; - } - - public final void setForce(boolean force) { - this.force = force; - } - - @Override - public final String requestedAction() { - return action; - } - - public final void setAction(String action) { - this.action = action; - } - - @Override - public final String requestedModule() { - return module; - } - - public final void setModule(String module) { - this.module = module; - } - - public final void setPendingRequestId(String pendingReqId) { - this.pendingRequestId = pendingReqId; - - } - - @Override - @NonNull - public final String getPendingRequestId() { - if (pendingRequestId == null) - throw new IllegalStateException("No PendingRequestId set!!!"); - - return pendingRequestId; - } - - @Override - public final String getInternalSSOSessionIdentifier() { - return this.internalSSOSessionId; - } - - @Override - public final void setInternalSSOSessionIdentifier(String internalSSOSessionId) { - this.internalSSOSessionId = internalSSOSessionId; - - } - - @Override - public final <T> T getSessionData(final Class<T> wrapper) { - if (wrapper != null) { - if (AuthProcessDataWrapper.class.isAssignableFrom(wrapper)) { - try { - return wrapper.getConstructor(Map.class).newInstance(this.genericDataStorage); - - } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException - | IllegalArgumentException | InvocationTargetException e) { - log.error("Can NOT instance wrapper: " + wrapper.getName(), e); - - } - - } - - log.error("Can NOT wrap generic data into session data. " - + "Reason: Wrapper " + wrapper.getName() + " is NOT a valid wrapper"); - throw new RuntimeException("Can NOT wrap generic data into session data. " - + "Reason: Wrapper " + wrapper.getName() + " is NOT a valid wrapper"); - - } - - return null; - - } - - @Override - public final ISPConfiguration getServiceProviderConfiguration() { - return this.spConfiguration; - - - } - - @Override - public <T> T getServiceProviderConfiguration(final Class<T> decorator) { - if (this.spConfiguration != null) { - if (decorator.isAssignableFrom(this.spConfiguration.getClass())) { - return (T) this.spConfiguration; - - } else - log.error("Can not decorate SP configuration by '" + decorator.getName() + "'."); - throw new RuntimeException("Can not decorate SP configuration by '" + decorator.getName() + "'."); - - } - - return null; - - } - - public void setOnlineApplicationConfiguration(ISPConfiguration spConfig) { - this.spConfiguration = spConfig; - - } - - @Override - public final String getUniqueTransactionIdentifier() { - return this.uniqueTransactionIdentifer; - - } - - @Override - public final String getUniqueSessionIdentifier() { - return this.uniqueSessionIdentifer; - - } - - @Override - public final String getProcessInstanceId() { - return this.processInstanceId; - - } - - public final void setUniqueTransactionIdentifier(String id) { - this.uniqueTransactionIdentifer = id; - - } - - public final void setUniqueSessionIdentifier(String id) { - this.uniqueSessionIdentifer = id; - - } - - public void setProcessInstanceId(String id) { - this.processInstanceId = id; - - } - - @Override - public final String getAuthURL() { - return this.idpAuthURL; - } - - @Override - public final String getAuthURLWithOutSlash() { - if (this.idpAuthURL.endsWith("/")) - return this.idpAuthURL.substring(0, this.idpAuthURL.length()-1); - else - return this.idpAuthURL; - - } - - @Override - public final boolean isNeedAuthentication() { - return needAuthentication; - } - - public final void setNeedAuthentication(boolean needAuthentication) { - this.needAuthentication = needAuthentication; - } - - @Override - public final boolean isAuthenticated() { - return isAuthenticated; - } - - @Override - public final void setAuthenticated(boolean isAuthenticated) { - this.isAuthenticated = isAuthenticated; - } - - @Override - public final boolean needSingleSignOnFunctionality() { - return needSSO; - } - @Override - public final void setNeedSingleSignOnFunctionality(boolean needSSO) { - this.needSSO = needSSO; - - } - - @Override - public final boolean isNeedUserConsent() { - return this.needUserConsent; - - } - - @Override - public final void setNeedUserConsent(boolean needConsent) { - this.needUserConsent = needConsent; - - } - - @Override - public final boolean isAbortedByUser() { - return this.isAbortedByUser; - } - - @Override - public final void setAbortedByUser(boolean isAborted) { - this.isAbortedByUser = isAborted; - - } - - @Override - public final Object getRawData(String key) { - if (StringUtils.isNotEmpty(key)) { - return genericDataStorage.get(key); - - } - - log.info("Can not load generic request-data with key='null'"); - return null; - } - - @Override - public final <T> T getRawData(String key, final Class<T> clazz) { - if (StringUtils.isNotEmpty(key)) { - final Object data = genericDataStorage.get(key); - - if (data == null) - return null; - - try { - @SuppressWarnings("unchecked") - final - T test = (T) data; - return test; - - } catch (final Exception e) { - log.warn("Generic request-data object can not be casted to requested type", e); - return null; - - } - - } - - log.info("Can not load generic request-data with key='null'"); - return null; - - } - - @Override - public final void setRawDataToTransaction(String key, Object object) throws EAAFStorageException { - if (StringUtils.isEmpty(key)) { - log.info("Generic request-data can not be stored with a 'null' key"); - throw new EAAFStorageException("Generic request-data can not be stored with a 'null' key", null); - - } - - if (object != null) { - if (!Serializable.class.isInstance(object)) { - log.warn("Generic request-data can only store objects which implements the 'Seralizable' interface"); - throw new EAAFStorageException("Generic request-data can only store objects which implements the 'Seralizable' interface", null); - - } - } - - if (genericDataStorage.containsKey(key)) - log.trace("Overwrite generic request-data with key:" + key); - else - log.trace("Add generic request-data with key:" + key + " to session."); - - genericDataStorage.put(key, object); - - } - - @Override - public final void setRawDataToTransaction(Map<String, Object> map) throws EAAFStorageException { - if (map == null) { - log.info("Generic request-data can not be stored with a 'null' map"); - throw new EAAFStorageException("Generic request-data can not be stored with a 'null' map", null); - - } - - //validate and store values - for (final Entry<String, Object> el : map.entrySet()) - setRawDataToTransaction(el.getKey(), el.getValue()); - - } - } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/AbstractLocaleAuthServletTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/AbstractLocaleAuthServletTask.java index 6b5f1a4c..dcd5a1d1 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/AbstractLocaleAuthServletTask.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/AbstractLocaleAuthServletTask.java @@ -10,80 +10,86 @@ import org.apache.commons.text.StringEscapeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.data.EAAFEventCodes; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.data.EaafEventCodes; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; public abstract class AbstractLocaleAuthServletTask extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(AbstractLocaleAuthServletTask.class); - - public static final String PROP_REQ_PARAM_LOCALE = "lang"; - - @Override - public final void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) - throws TaskExecutionException { - - final Serializable changeLangFlag = executionContext.get(EAAFConstants.PROCESSCONTEXT_SWITCH_LANGUAGE); - final String localeParam = StringEscapeUtils.escapeHtml4(request.getParameter(PROP_REQ_PARAM_LOCALE)); - if (StringUtils.isNotEmpty(localeParam) && - (changeLangFlag == null || !((Boolean)changeLangFlag)) ) { - log.debug("Find {} parameter. Reload last task with new locale: {}", PROP_REQ_PARAM_LOCALE, localeParam); - executionContext.put(EAAFConstants.PROCESSCONTEXT_SWITCH_LANGUAGE, true); - - - - } else { - log.trace("Find {} parameter. Processing this task ... ",PROP_REQ_PARAM_LOCALE); - executionContext.put(EAAFConstants.PROCESSCONTEXT_SWITCH_LANGUAGE, false); - - if (parseFlagFromHttpRequest(request, EAAFConstants.PARAM_HTTP_STOP_PROCESS, false)) { - log.info("Authentication process WAS stopped by entity. Stopping auth. process ... "); - stopProcessFromUserDecision(executionContext, request, response); - - } else - executeWithLocale(executionContext, request, response); - - } - - } - - protected void stopProcessFromUserDecision(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException { - try { - revisionsLogger.logEvent(pendingReq, EAAFEventCodes.PROCESS_STOPPED_BY_USER); - pendingReq.setAbortedByUser(true); - pendingReq.setAuthenticated(false); - performRedirectToProtocolFinialization(executionContext, pendingReq, request, response); - - log.trace("Set process-cancelation flag"); - executionContext.setCanceleProcessFlag(); - - } catch (final EAAFException e) { - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - - } catch (final Exception e) { - log.warn("Stopping auth.process FAILED", e); - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - - } - - } - - protected boolean parseFlagFromHttpRequest(HttpServletRequest httpReq, String httpParamName, boolean defaultValue) { - final String flag = httpReq.getParameter(httpParamName); - log.trace("Get httpParam: {} with value: {}", httpParamName, flag); - if (StringUtils.isNotEmpty(httpParamName)) { - return Boolean.parseBoolean(flag); - - } else { - return defaultValue; - } - - } - - protected abstract void executeWithLocale(ExecutionContext executionContext, HttpServletRequest request, - HttpServletResponse response) throws TaskExecutionException; + private static final Logger log = LoggerFactory.getLogger(AbstractLocaleAuthServletTask.class); + + public static final String PROP_REQ_PARAM_LOCALE = "lang"; + + @Override + public final void execute(final ExecutionContext executionContext, + final HttpServletRequest request, final HttpServletResponse response) + throws TaskExecutionException { + + final Serializable changeLangFlag = + executionContext.get(EaafConstants.PROCESSCONTEXT_SWITCH_LANGUAGE); + final String localeParam = + StringEscapeUtils.escapeHtml4(request.getParameter(PROP_REQ_PARAM_LOCALE)); + if (StringUtils.isNotEmpty(localeParam) + && (changeLangFlag == null || !((Boolean) changeLangFlag))) { + log.debug("Find {} parameter. Reload last task with new locale: {}", PROP_REQ_PARAM_LOCALE, + localeParam); + executionContext.put(EaafConstants.PROCESSCONTEXT_SWITCH_LANGUAGE, true); + + } else { + log.trace("Find {} parameter. Processing this task ... ", PROP_REQ_PARAM_LOCALE); + executionContext.put(EaafConstants.PROCESSCONTEXT_SWITCH_LANGUAGE, false); + + if (parseFlagFromHttpRequest(request, EaafConstants.PARAM_HTTP_STOP_PROCESS, false)) { + log.info("Authentication process WAS stopped by entity. Stopping auth. process ... "); + stopProcessFromUserDecision(executionContext, request, response); + + } else { + executeWithLocale(executionContext, request, response); + } + + } + + } + + protected void stopProcessFromUserDecision(final ExecutionContext executionContext, + final HttpServletRequest request, final HttpServletResponse response) + throws TaskExecutionException { + try { + revisionsLogger.logEvent(pendingReq, EaafEventCodes.PROCESS_STOPPED_BY_USER); + pendingReq.setAbortedByUser(true); + pendingReq.setAuthenticated(false); + performRedirectToProtocolFinialization(executionContext, pendingReq, request, response); + + log.trace("Set process-cancelation flag"); + executionContext.setCanceleProcessFlag(); + + } catch (final EaafException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (final Exception e) { + log.warn("Stopping auth.process FAILED", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + + } + + protected boolean parseFlagFromHttpRequest(final HttpServletRequest httpReq, + final String httpParamName, final boolean defaultValue) { + final String flag = httpReq.getParameter(httpParamName); + log.trace("Get httpParam: {} with value: {}", httpParamName, flag); + if (StringUtils.isNotEmpty(httpParamName)) { + return Boolean.parseBoolean(flag); + + } else { + return defaultValue; + } + + } + + protected abstract void executeWithLocale(ExecutionContext executionContext, + HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException; } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java index b12a69b2..892121c0 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.controller.tasks; import javax.servlet.http.HttpServletRequest; @@ -33,49 +26,55 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; import at.gv.egiz.eaaf.core.api.idp.auth.IAuthenticationManager; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; /** + * Finalize the authentication process-flow. + * * @author tlenz * */ @Component("FinalizeAuthenticationTask") public class FinalizeAuthenticationTask extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(FinalizeAuthenticationTask.class); - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) - */ - @Override - public void execute(ExecutionContext executionContext, - HttpServletRequest request, HttpServletResponse response) - throws TaskExecutionException { - - try { - //set pending request to authenticated - pendingReq.setAuthenticated(true); - revisionsLogger.logEvent(pendingReq, IAuthenticationManager.EVENT_AUTHENTICATION_PROCESS_FINISHED); - performRedirectToProtocolFinialization(executionContext, pendingReq, request, response); - - - } catch (final EAAFException e) { - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - - } catch (final Exception e) { - log.warn("FinalizeAuthenticationTask has an internal error", e); - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - - } finally { - executionContext.remove(EAAFConstants.PROCESS_ENGINE_PENDINGREQUESTID); - - } - - } + private static final Logger log = LoggerFactory.getLogger(FinalizeAuthenticationTask.class); + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv. + * egovernment.moa.id.process. api.ExecutionContext, + * javax.servlet.http.HttpServletRequest, + * javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(final ExecutionContext executionContext, final HttpServletRequest request, + final HttpServletResponse response) throws TaskExecutionException { + + try { + // set pending request to authenticated + pendingReq.setAuthenticated(true); + revisionsLogger.logEvent(pendingReq, + IAuthenticationManager.EVENT_AUTHENTICATION_PROCESS_FINISHED); + performRedirectToProtocolFinialization(executionContext, pendingReq, request, response); + + } catch (final EaafException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (final Exception e) { + log.warn("FinalizeAuthenticationTask has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } finally { + executionContext.remove(EaafConstants.PROCESS_ENGINE_PENDINGREQUESTID); + + } + + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java index 5ea5baa1..328a25c5 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.controller.tasks; import java.util.Set; @@ -38,7 +31,7 @@ import org.springframework.stereotype.Component; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.ModuleRegistration; @@ -46,76 +39,89 @@ import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; /** + * Restart the authentication process-flow. + * * @author tlenz * */ @Component("RestartAuthProzessManagement") -public class RestartAuthProzessManagement extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(RestartAuthProzessManagement.class); - - @Autowired ProcessEngine processEngine; - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) - */ - @Override - public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) - throws TaskExecutionException { - try { - - if (this.pendingReq.isAbortedByUser()) { - log.debug("AuthProcess was stopped. Forward to finalization ... "); - performRedirectToProtocolFinialization(executionContext, pendingReq, request, response); - - } else { - //create a new execution context and copy all elements to new context - final ExecutionContext newec = new ExecutionContextImpl(); - final Set<String> entries = executionContext.keySet(); - for (final String key : entries) { - newec.put(key, executionContext.get(key)); - - } - - log.debug("Select new auth.-process and restart restart process-engine ... "); - - // select and create new process instance - final String processDefinitionId = ModuleRegistration.getInstance().selectProcess(newec, pendingReq); - if (processDefinitionId == null) { - log.warn("No suitable authentication process found for SessionID " + pendingReq.getPendingRequestId()); - throw new EAAFException("process.02", new Object[] { pendingReq.getPendingRequestId()}); - } - - final String processInstanceId = processEngine.createProcessInstance(processDefinitionId, newec); - - // keep process instance id in moa session - ((RequestImpl)pendingReq).setProcessInstanceId(processInstanceId); - - // make sure pending request has been persisted before running the process - try { - requestStoreage.storePendingRequest(pendingReq); - - } catch (final EAAFException e) { - log.error("Database Error! MOASession is not stored!"); - throw new EAAFException("internal.02", null); - - } - - log.info("Restart process-engine with auth.process:" + processDefinitionId); - - // start process - processEngine.start(pendingReq); - - } - - } catch (final EAAFException e) { - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - - } catch (final Exception e) { - log.warn("RestartAuthProzessManagement has an internal error", e); - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - - } - - } +public class RestartAuthProzessManagement extends AbstractAuthServletTask { + private static final Logger log = LoggerFactory.getLogger(RestartAuthProzessManagement.class); + + @Autowired + ProcessEngine processEngine; + @Autowired + ModuleRegistration moduleRegistration; + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv. + * egovernment.moa.id.process. api.ExecutionContext, + * javax.servlet.http.HttpServletRequest, + * javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(final ExecutionContext executionContext, final HttpServletRequest request, + final HttpServletResponse response) throws TaskExecutionException { + try { + + if (this.pendingReq.isAbortedByUser()) { + log.debug("AuthProcess was stopped. Forward to finalization ... "); + performRedirectToProtocolFinialization(executionContext, pendingReq, request, response); + + } else { + // create a new execution context and copy all elements to new context + final ExecutionContext newec = new ExecutionContextImpl(); + final Set<String> entries = executionContext.keySet(); + for (final String key : entries) { + newec.put(key, executionContext.get(key)); + + } + + log.debug("Select new auth.-process and restart restart process-engine ... "); + + // select and create new process instance + final String processDefinitionId = + moduleRegistration.selectProcess(newec, pendingReq); + if (processDefinitionId == null) { + log.warn("No suitable authentication process found for SessionID " + + pendingReq.getPendingRequestId()); + throw new EaafException("process.02", new Object[] { pendingReq.getPendingRequestId() }); + } + + final String processInstanceId = + processEngine.createProcessInstance(processDefinitionId, newec); + + // keep process instance id in moa session + ((RequestImpl) pendingReq).setProcessInstanceId(processInstanceId); + + // make sure pending request has been persisted before running the process + try { + requestStoreage.storePendingRequest(pendingReq); + + } catch (final EaafException e) { + log.error("Database Error! MOASession is not stored!"); + throw new EaafException("internal.02", null); + + } + + log.info("Restart process-engine with auth.process:" + processDefinitionId); + + // start process + processEngine.start(pendingReq); + + } + + } catch (final EaafException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (final Exception e) { + log.warn("RestartAuthProzessManagement has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExecutionContextImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExecutionContextImpl.java index 3cd696df..27bc829d 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExecutionContextImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExecutionContextImpl.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process; import java.io.Serializable; @@ -36,82 +29,84 @@ import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; /** * ExecutionContext implementation, related to a certain process instance. - * + * * @author tknall - * + * */ public class ExecutionContextImpl implements ExecutionContext { - private static final long serialVersionUID = 1L; - - private final Map<String, Serializable> ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>()); - - private String processInstanceId; - private boolean markedAsCancelled = false; - - /** - * Creates a new instance. - */ - public ExecutionContextImpl() { - } - - /** - * Creates a new instance and associated it with a certain process instance. - */ - public ExecutionContextImpl(String processInstanceId) { - this.processInstanceId = processInstanceId; - } - - @Override - public void setProcessInstanceId(String processInstanceId) { - this.processInstanceId = processInstanceId; - } - - @Override - public String getProcessInstanceId() { - return processInstanceId; - } - - @Override - public Serializable get(String key) { - return ctxData.get(key); - } - - @Override - public Serializable remove(String key) { - return ctxData.remove(key); - } - - @Override - public void put(String key, Serializable object) { - ctxData.put(key, object); - } - - @Override - public Set<String> keySet() { - return Collections.unmodifiableSet(ctxData.keySet()); - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("ExecutionContextImpl ["); - builder.append("id=").append(processInstanceId); - builder.append(", variables="); - builder.append(ctxData.keySet()); - builder.append("]"); - return builder.toString(); - } - - @Override - public boolean isProcessCancelled() { - return markedAsCancelled; - } - - @Override - public void setCanceleProcessFlag() { - markedAsCancelled = true; - - } + private static final long serialVersionUID = 1L; + + private final Map<String, Serializable> ctxData = + Collections.synchronizedMap(new HashMap<String, Serializable>()); + + private String processInstanceId; + private boolean markedAsCancelled = false; + + /** + * Creates a new instance. + */ + public ExecutionContextImpl() { + + } + + /** + * Creates a new instance and associated it with a certain process instance. + */ + public ExecutionContextImpl(final String processInstanceId) { + this.processInstanceId = processInstanceId; + } + + @Override + public void setProcessInstanceId(final String processInstanceId) { + this.processInstanceId = processInstanceId; + } + + @Override + public String getProcessInstanceId() { + return processInstanceId; + } + + @Override + public Serializable get(final String key) { + return ctxData.get(key); + } + + @Override + public Serializable remove(final String key) { + return ctxData.remove(key); + } + + @Override + public void put(final String key, final Serializable object) { + ctxData.put(key, object); + } + + @Override + public Set<String> keySet() { + return Collections.unmodifiableSet(ctxData.keySet()); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("ExecutionContextImpl ["); + builder.append("id=").append(processInstanceId); + builder.append(", variables="); + builder.append(ctxData.keySet()); + builder.append("]"); + return builder.toString(); + } + + @Override + public boolean isProcessCancelled() { + return markedAsCancelled; + } + + @Override + public void setCanceleProcessFlag() { + markedAsCancelled = true; + + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExpressionEvaluationContextImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExpressionEvaluationContextImpl.java index 694b8d0d..67604a03 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExpressionEvaluationContextImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExpressionEvaluationContextImpl.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process; import java.io.Serializable; @@ -37,34 +30,34 @@ import at.gv.egiz.eaaf.core.api.idp.process.ExpressionEvaluationContext; /** * Context implementation used for expression evaluation only. - * + * * @author tknall - * + * */ public class ExpressionEvaluationContextImpl implements ExpressionEvaluationContext { - private static final long serialVersionUID = 1L; - - private Map<String, Serializable> ctxData; - - /** - * Creates a new instance and initializes it with data from a given process instance. - * - * @param processInstance - * The process instance. - */ - ExpressionEvaluationContextImpl(ProcessInstance processInstance) { - ExecutionContext executionContext = processInstance.getExecutionContext(); - Set<String> keys = executionContext.keySet(); - ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>(keys.size())); - for (String key : keys) { - ctxData.put(key, executionContext.get(key)); - } - } - - @Override - public Map<String, Serializable> getCtx() { - return Collections.unmodifiableMap(ctxData); - } + private static final long serialVersionUID = 1L; + + private final Map<String, Serializable> ctxData; + + /** + * Creates a new instance and initializes it with data from a given process + * instance. + * + * @param processInstance The process instance. + */ + ExpressionEvaluationContextImpl(final ProcessInstance processInstance) { + final ExecutionContext executionContext = processInstance.getExecutionContext(); + final Set<String> keys = executionContext.keySet(); + ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>(keys.size())); + for (final String key : keys) { + ctxData.put(key, executionContext.get(key)); + } + } + + @Override + public Map<String, Serializable> getCtx() { + return Collections.unmodifiableMap(ctxData); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParser.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParser.java index f817f9fb..14537d44 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParser.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParser.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process; import java.io.IOException; @@ -61,190 +54,214 @@ import at.gv.egiz.eaaf.core.impl.idp.process.model.TaskInfo; import at.gv.egiz.eaaf.core.impl.idp.process.model.Transition; /** - * Parses an XML representation of a process definition as defined by the respective XML schema. - * <p/ - * The parser is thread-safe. + * Parses an XML representation of a process definition as defined by the + * respective XML schema. The parser is thread-safe. + * * @author tknall * */ public class ProcessDefinitionParser { - - private static final String NS = "http://reference.e-government.gv.at/namespace/moa/process/definition/v1"; - - private static Logger log = LoggerFactory.getLogger(ProcessDefinitionParser.class); - - private static class LazyProcessDefinitionSchemaHolder { - private static final Schema PD_SCHEMA_INSTANCE; - static { - try (InputStream in = ProcessDefinitionParser.class.getResourceAsStream("/process/ProcessDefinition.xsd")) { - log.trace("Compiling process definition schema."); - SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - // schema is thread-safe - PD_SCHEMA_INSTANCE = factory.newSchema(new StreamSource(in)); - } catch (Exception e) { - throw new RuntimeException("Unable to compile process definition schema.", e); - } - } - } - - /** - * Parses an XML representation of a process definition. The representation is being validated in order to suffice - * the related XML schema. - * - * @param processDefinitionInputStream - * The process definition. - * @return A new process definition. - * @throws ProcessDefinitionParserException - * Thrown in case of error parsing the process definition. - */ - public ProcessDefinition parse(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException { - XMLEventReader reader = null; - final ProcessDefinition pd = new ProcessDefinition(); - log.debug("Parsing and validating process definition."); - try { - - // Standard implementation of XMLInputFactory seems not to be thread-safe - XMLInputFactory inputFactory = XMLInputFactory.newInstance(); - reader = inputFactory.createXMLEventReader(processDefinitionInputStream); - - final List<StartElement> transitionElements = new ArrayList<>(); - final List<StartEvent> startEvents = new ArrayList<>(); - - reader = new EventReaderDelegate(reader) { - - @Override - public XMLEvent nextEvent() throws XMLStreamException { - XMLEvent event = super.nextEvent(); - - switch (event.getEventType()) { - case XMLStreamConstants.START_ELEMENT: - StartElement element = event.asStartElement(); - QName qname = element.getName(); - - if (NS.equals(qname.getNamespaceURI())) { - log.trace("Found process description element '{}'.", qname.getLocalPart()); - Attribute id = element.getAttributeByName(new QName("id")); - - switch (qname.getLocalPart()) { - case "ProcessDefinition": - if (id != null) { - pd.setId(id.getValue()); - } - break; - case "StartEvent": - StartEvent startEvent = new StartEvent(); - if (id != null) { - startEvent.setId(id.getValue()); - } - startEvents.add(startEvent); - break; - case "EndEvent": - EndEvent endEvent = new EndEvent(); - if (id != null) { - endEvent.setId(id.getValue()); - pd.getEndEvents().put(id.getValue(), endEvent); - } - break; - case "Transition": - transitionElements.add(element); - break; - case "Task": - TaskInfo taskInfo = new TaskInfo(); - if (id != null) { - taskInfo.setId(id.getValue()); - pd.getTaskInfos().put(id.getValue(), taskInfo); - } - Attribute async = element.getAttributeByName(new QName("async")); - if (async != null) { - taskInfo.setAsync(Boolean.valueOf(async.getValue())); - } - Attribute implementingClass = element.getAttributeByName(new QName("class")); - if (implementingClass != null) { - taskInfo.setTaskImplementingClass(implementingClass.getValue()); - } - break; - } - - } - - break; - } - - return event; - } - - }; - - // validator is not thread-safe - Validator validator = LazyProcessDefinitionSchemaHolder.PD_SCHEMA_INSTANCE.newValidator(); - validator.validate(new StAXSource(reader)); - log.trace("Process definition successfully schema validated."); - - // perform some basic checks - log.trace("Building model and performing some plausibility checks."); - if (startEvents.size() != 1) { - throw new ProcessDefinitionParserException("A ProcessDefinition must contain exactly one single StartEvent."); - } - pd.setStartEvent(startEvents.get(0)); - - // link transitions - Iterator<StartElement> transitions = transitionElements.iterator(); - while (transitions.hasNext()) { - StartElement element = transitions.next(); - Transition transition = new Transition(); - Attribute id = element.getAttributeByName(new QName("id")); - if (id != null) { - transition.setId(id.getValue()); - } - Attribute conditionExpression = element.getAttributeByName(new QName("conditionExpression")); - if (conditionExpression != null) { - transition.setConditionExpression(conditionExpression.getValue()); - } - Attribute from = element.getAttributeByName(new QName("from")); - if (from != null) { - ProcessNode fromNode = pd.getProcessNode(from.getValue()); - if (fromNode == null) { - throw new ProcessDefinitionParserException("Transition's 'from'-attribute refers to a non-existing event or task '" + from.getValue() + '.'); - } - if (fromNode instanceof EndEvent) { - throw new ProcessDefinitionParserException("Transition cannot start from end event."); - } - transition.setFrom(fromNode); - fromNode.getOutgoingTransitions().add(transition); - } - Attribute to = element.getAttributeByName(new QName("to")); - if (to != null) { - ProcessNode toNode = pd.getProcessNode(to.getValue()); - if (toNode == null) { - throw new ProcessDefinitionParserException("Transition's 'to'-attribute refers to a non-existing event or task '" + to.getValue() + '.'); - } - transition.setTo(toNode); - toNode.getIncomingTransitions().add(transition); - } - if (transition.getConditionExpression() == null && Objects.equals(transition.getFrom(), transition.getTo())) { - throw new ProcessDefinitionParserException("Transition's 'from' equals its 'to'. Since no 'conditionExpression' has been set this will cause a loop."); - } - } - log.debug("Process definition '{}' successfully parsed.", pd.getId()); - return pd; - - } catch (ProcessDefinitionParserException e) { - throw e; - } catch (XMLStreamException|IOException e) { - throw new ProcessDefinitionParserException("Unable to read process definition from inputstream.", e); - } catch (SAXException e) { - throw new ProcessDefinitionParserException("Schema validation of process description failed.", e); - } catch (Exception e) { - throw new ProcessDefinitionParserException("Internal error creating process definition from inputstream.", e); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (XMLStreamException e) { - // error freeing resources - } - } - } - } + + private static final String NS = + "http://reference.e-government.gv.at/namespace/moa/process/definition/v1"; + + private static Logger log = LoggerFactory.getLogger(ProcessDefinitionParser.class); + + private static class LazyProcessDefinitionSchemaHolder { + private static final Schema PD_SCHEMA_INSTANCE; + + static { + try (InputStream in = + ProcessDefinitionParser.class.getResourceAsStream("/process/ProcessDefinition.xsd")) { + log.trace("Compiling process definition schema."); + final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + // schema is thread-safe + PD_SCHEMA_INSTANCE = factory.newSchema(new StreamSource(in)); + } catch (final Exception e) { + throw new RuntimeException("Unable to compile process definition schema.", e); + } + } + } + + /** + * Parses an XML representation of a process definition. The representation is + * being validated in order to suffice the related XML schema. + * + * @param processDefinitionInputStream The process definition. + * @return A new process definition. + * @throws ProcessDefinitionParserException Thrown in case of error parsing the + * process definition. + */ + public ProcessDefinition parse(final InputStream processDefinitionInputStream) + throws ProcessDefinitionParserException { + XMLEventReader reader = null; + final ProcessDefinition pd = new ProcessDefinition(); + log.debug("Parsing and validating process definition."); + try { + + // Standard implementation of XMLInputFactory seems not to be thread-safe + final XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + reader = inputFactory.createXMLEventReader(processDefinitionInputStream); + + final List<StartElement> transitionElements = new ArrayList<>(); + final List<StartEvent> startEvents = new ArrayList<>(); + + reader = new EventReaderDelegate(reader) { + + @Override + public XMLEvent nextEvent() throws XMLStreamException { + final XMLEvent event = super.nextEvent(); + + switch (event.getEventType()) { + case XMLStreamConstants.START_ELEMENT: + final StartElement element = event.asStartElement(); + final QName qname = element.getName(); + + if (NS.equals(qname.getNamespaceURI())) { + log.trace("Found process description element '{}'.", qname.getLocalPart()); + final Attribute id = element.getAttributeByName(new QName("id")); + + switch (qname.getLocalPart()) { + case "ProcessDefinition": + if (id != null) { + pd.setId(id.getValue()); + } + break; + case "StartEvent": + final StartEvent startEvent = new StartEvent(); + if (id != null) { + startEvent.setId(id.getValue()); + } + startEvents.add(startEvent); + break; + case "EndEvent": + final EndEvent endEvent = new EndEvent(); + if (id != null) { + endEvent.setId(id.getValue()); + pd.getEndEvents().put(id.getValue(), endEvent); + } + break; + case "Transition": + transitionElements.add(element); + break; + case "Task": + final TaskInfo taskInfo = new TaskInfo(); + if (id != null) { + taskInfo.setId(id.getValue()); + pd.getTaskInfos().put(id.getValue(), taskInfo); + } + final Attribute async = element.getAttributeByName(new QName("async")); + if (async != null) { + taskInfo.setAsync(Boolean.valueOf(async.getValue())); + } + final Attribute implementingClass = + element.getAttributeByName(new QName("class")); + if (implementingClass != null) { + taskInfo.setTaskImplementingClass(implementingClass.getValue()); + } + break; + default: + log.info("Ignore unknown event: {}", qname); + break; + } + + } + + break; + default: + log.trace("Ignore unknown event: {}", event); + break; + } + + return event; + } + + }; + + // validator is not thread-safe + final Validator validator = + LazyProcessDefinitionSchemaHolder.PD_SCHEMA_INSTANCE.newValidator(); + validator.validate(new StAXSource(reader)); + log.trace("Process definition successfully schema validated."); + + // perform some basic checks + log.trace("Building model and performing some plausibility checks."); + if (startEvents.size() != 1) { + throw new ProcessDefinitionParserException( + "A ProcessDefinition must contain exactly one single StartEvent."); + } + pd.setStartEvent(startEvents.get(0)); + + // link transitions + final Iterator<StartElement> transitions = transitionElements.iterator(); + while (transitions.hasNext()) { + final StartElement element = transitions.next(); + final Transition transition = new Transition(); + final Attribute id = element.getAttributeByName(new QName("id")); + if (id != null) { + transition.setId(id.getValue()); + } + final Attribute conditionExpression = + element.getAttributeByName(new QName("conditionExpression")); + if (conditionExpression != null) { + transition.setConditionExpression(conditionExpression.getValue()); + } + final Attribute from = element.getAttributeByName(new QName("from")); + if (from != null) { + final ProcessNode fromNode = pd.getProcessNode(from.getValue()); + if (fromNode == null) { + throw new ProcessDefinitionParserException( + "Transition's 'from'-attribute refers to a non-existing event or task '" + + from.getValue() + '.'); + } + if (fromNode instanceof EndEvent) { + throw new ProcessDefinitionParserException("Transition cannot start from end event."); + } + transition.setFrom(fromNode); + fromNode.getOutgoingTransitions().add(transition); + } + final Attribute to = element.getAttributeByName(new QName("to")); + if (to != null) { + final ProcessNode toNode = pd.getProcessNode(to.getValue()); + if (toNode == null) { + throw new ProcessDefinitionParserException( + "Transition's 'to'-attribute refers to a non-existing event or task '" + + to.getValue() + '.'); + } + transition.setTo(toNode); + toNode.getIncomingTransitions().add(transition); + } + if (transition.getConditionExpression() == null + && Objects.equals(transition.getFrom(), transition.getTo())) { + throw new ProcessDefinitionParserException( + "Transition's 'from' equals its 'to'. Since no 'conditionExpression' " + + "has been set this will cause a loop."); + } + } + log.debug("Process definition '{}' successfully parsed.", pd.getId()); + return pd; + + } catch (final ProcessDefinitionParserException e) { + throw e; + } catch (XMLStreamException | IOException e) { + throw new ProcessDefinitionParserException( + "Unable to read process definition from inputstream.", e); + } catch (final SAXException e) { + throw new ProcessDefinitionParserException("Schema validation of process description failed.", + e); + } catch (final Exception e) { + throw new ProcessDefinitionParserException( + "Internal error creating process definition from inputstream.", e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (final XMLStreamException e) { + e.printStackTrace(); + + } + } + } + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParserException.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParserException.java index 292b3881..d7d4928c 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParserException.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessDefinitionParserException.java @@ -1,61 +1,53 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process; /** * Exception thrown in case of error parsing a process definition. - * + * * @author tknall - * + * */ public class ProcessDefinitionParserException extends Exception { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - /** - * Creates a new parser exception providing a {@code message} describing the reason and the {@code cause}. - * - * @param message - * The message. - * @param cause - * The cause. - */ - public ProcessDefinitionParserException(String message, Throwable cause) { - super(message, cause); - } + /** + * Creates a new parser exception providing a {@code message} describing the + * reason and the {@code cause}. + * + * @param message The message. + * @param cause The cause. + */ + public ProcessDefinitionParserException(final String message, final Throwable cause) { + super(message, cause); + } - /** - * Creates a new parser exception providing a {@code message} describing the reason. - * - * @param message - * The message. - */ - public ProcessDefinitionParserException(String message) { - super(message); - } + /** + * Creates a new parser exception providing a {@code message} describing the + * reason. + * + * @param message The message. + */ + public ProcessDefinitionParserException(final String message) { + super(message); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java index 53f50e1f..9274ea81 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java @@ -1,39 +1,32 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process; import java.io.InputStream; import java.io.Serializable; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.collections4.IterableUtils; -import org.apache.commons.collections4.Predicate; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,14 +35,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; 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.EaafConstants; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.api.idp.process.ExpressionEvaluationContext; import at.gv.egiz.eaaf.core.api.idp.process.ExpressionEvaluator; import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine; -import at.gv.egiz.eaaf.core.api.idp.process.ProcessInstanceStoreDAO; +import at.gv.egiz.eaaf.core.api.idp.process.ProcessInstanceStoreDao; import at.gv.egiz.eaaf.core.api.idp.process.Task; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; import at.gv.egiz.eaaf.core.impl.idp.process.dao.ProcessInstanceStore; import at.gv.egiz.eaaf.core.impl.idp.process.model.EndEvent; @@ -60,437 +53,486 @@ import at.gv.egiz.eaaf.core.impl.idp.process.model.TaskInfo; import at.gv.egiz.eaaf.core.impl.idp.process.model.Transition; /** - * Process engine implementation allowing starting and continuing processes as well as providing means for cleanup actions. + * Process engine implementation allowing starting and continuing processes as + * well as providing means for cleanup actions. */ public class ProcessEngineImpl implements ProcessEngine { - - private final Logger log = LoggerFactory.getLogger(getClass()); - - @Autowired ProcessInstanceStoreDAO piStoreDao; - @Autowired ApplicationContext context; - - private final ProcessDefinitionParser pdp = new ProcessDefinitionParser(); - - private final Map<String, ProcessDefinition> processDefinitions = new ConcurrentHashMap<String, ProcessDefinition>(); - - private final static String MDC_CTX_PI_NAME = "processInstanceId"; - private final static String MDC_CTX_TASK_NAME = "taskId"; - - private ExpressionEvaluator transitionConditionExpressionEvaluator; - - @Override - public void registerProcessDefinition(ProcessDefinition processDefinition) { - log.info("Registering process definition '{}'.", processDefinition.getId()); - processDefinitions.put(processDefinition.getId(), processDefinition); - } - - @Override - public String registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException{ - final ProcessDefinition pd = pdp.parse(processDefinitionInputStream); - - postValidationOfProcessDefintion(pd); - - registerProcessDefinition(pd); - return pd.getId(); - } - - /** - * Sets the process definitions. - * - * @param processDefinitions - * The process definitions. - * @throws IllegalArgumentException - * In case the process definitions contain definitions with the same identifier. - */ - public void setProcessDefinitions(Iterable<ProcessDefinition> processDefinitions) { - this.processDefinitions.clear(); - for (final ProcessDefinition pd : processDefinitions) { - if (this.processDefinitions.containsKey(pd.getId())) { - throw new IllegalArgumentException("Duplicate process definition identifier '" + pd.getId() + "'."); - } - registerProcessDefinition(pd); - } - } - - /** - * Sets an expression evaluator that should be used to process transition condition expressions. - * @param transitionConditionExpressionEvaluator The expression evaluator. - */ - public void setTransitionConditionExpressionEvaluator( - ExpressionEvaluator transitionConditionExpressionEvaluator) { - this.transitionConditionExpressionEvaluator = transitionConditionExpressionEvaluator; - } - - - @Override - public String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException { - // look for respective process definition - final ProcessDefinition pd = processDefinitions.get(processDefinitionId); - if (pd == null) { - throw new ProcessExecutionException("Unable to find process definition for process '" + processDefinitionId + "'."); - } - // create and keep process instance - final ProcessInstance pi = new ProcessInstance(pd, executionContext); - log.info("Creating process instance from process definition '{}': {}", processDefinitionId, pi.getId()); - - try { - saveOrUpdateProcessInstance(pi); - - } catch (final EAAFException e) { - throw new ProcessExecutionException("Unable to persist process instance.", e); - } - - return pi.getId(); - } - - @Override - public String createProcessInstance(String processDefinitionId) throws ProcessExecutionException { - return createProcessInstance(processDefinitionId, null); - } - - @Override - public void start(IRequest pendingReq) throws ProcessExecutionException { - try { - if (StringUtils.isEmpty(pendingReq.getProcessInstanceId())) { - log.error("Pending-request with id:" + pendingReq.getPendingRequestId() - + " includes NO 'ProcessInstanceId'"); - throw new ProcessExecutionException("Pending-request with id:" + pendingReq.getPendingRequestId() - + " includes NO 'ProcessInstanceId'"); - } - - final ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId()); - - if (pi == null ) { - throw new ProcessExecutionException("Process instance '" + pendingReq.getProcessInstanceId() + "' does not exist."); - - } - - MDC.put(MDC_CTX_PI_NAME, pi.getId()); - - if (!ProcessInstanceState.NOT_STARTED.equals(pi.getState())) { - throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has already been started (current state is " + pi.getState() + ")."); - } - log.info("Starting process instance '{}'.", pi.getId()); - // execute process - pi.setState(ProcessInstanceState.STARTED); - execute(pi, pendingReq); - - //store ProcessInstance if it is not already ended - if (!ProcessInstanceState.ENDED.equals(pi.getState())) - saveOrUpdateProcessInstance(pi); - - } catch (final EAAFException e) { - throw new ProcessExecutionException("Unable to load/save process instance.", e); - - } finally { - MDC.remove(MDC_CTX_PI_NAME); - } - } - - @Override - public void signal(IRequest pendingReq) throws ProcessExecutionException { - - try { - if (StringUtils.isEmpty(pendingReq.getProcessInstanceId())) { - log.error("Pending-request with id:" + pendingReq.getPendingRequestId() - + " includes NO 'ProcessInstanceId'"); - throw new ProcessExecutionException("Pending-request with id:" + pendingReq.getPendingRequestId() - + " includes NO 'ProcessInstanceId'"); - } - - final ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId()); - - if (pi == null ) { - throw new ProcessExecutionException("Process instance '" + pendingReq.getProcessInstanceId() + "' does not exist."); - - } - - MDC.put(MDC_CTX_PI_NAME, pi.getId()); - - if (!ProcessInstanceState.SUSPENDED.equals(pi.getState())) { - throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has not been suspended (current state is " + pi.getState() + ")."); - } - - log.debug("Waking up process instance '{}'.", pi.getId()); - pi.setState(ProcessInstanceState.STARTED); - - //put pending-request ID on execution-context because it could be changed - pi.getExecutionContext().put(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId()); - - execute(pi, pendingReq); - - //store ProcessInstance if it is not already ended - if (!ProcessInstanceState.ENDED.equals(pi.getState())) - saveOrUpdateProcessInstance(pi); - - } catch (final EAAFException e) { - throw new ProcessExecutionException("Unable to load/save process instance.", e); - - } finally { - MDC.remove(MDC_CTX_PI_NAME); - } - } - - - /** - * Instantiates a task implementation given by a {@link TaskInfo}. - * @param ti The task info. - * @return A Task implementation or {@code null} if the task info does not reference any task implementing classes. - * @throws ProcessExecutionException Thrown in case of error (when the referenced class does not implement {@link Task} for instance). - */ - private Task createTaskInstance(TaskInfo ti) throws ProcessExecutionException { - final String clazz = StringUtils.trimToNull(ti.getTaskImplementingClass()); - Task task = null; - - if (clazz != null) { - log.debug("Instantiating task implementing class '{}'.", clazz); - Object instanceClass = null; - try { - instanceClass = context.getBean(clazz); - - } catch (final Exception e) { - throw new ProcessExecutionException("Unable to get class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); - - } - if (instanceClass == null || !(instanceClass instanceof Task)) { - throw new ProcessExecutionException("Class '" + clazz + "' associated with task '" + ti.getId() + "' is not assignable to " + Task.class.getName() + "."); - - } - try { - task = (Task) instanceClass; - - } catch (final Exception e) { - throw new ProcessExecutionException("Unable to instantiate class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); - } - } - - return task; - } - - /** - * Starts/executes a given process instance. - * @param pi The process instance. - * @param pendingReq - * @throws ProcessExecutionException Thrown in case of error. - */ - private void execute(final ProcessInstance pi, IRequest pendingReq) throws ProcessExecutionException { - if (ProcessInstanceState.ENDED.equals(pi.getState())) { - throw new ProcessExecutionException("Process for instance '" + pi.getId() + "' has already been ended."); - } - final ProcessDefinition pd = pi.getProcessDefinition(); - final ProcessNode processNode = pd.getProcessNode(pi.getNextId()); - log.debug("Processing node '{}'.", processNode.getId()); - - // distinguish process node types StartEvent, TaskInfo and EndEvent - - if (processNode instanceof TaskInfo) { - // TaskInfo types need to be executed - final TaskInfo ti = (TaskInfo) processNode; - MDC.put(MDC_CTX_TASK_NAME, ti.getId()); - try { - log.debug("Processing task '{}'.", ti.getId()); - final Task task = createTaskInstance(ti); - if (task != null) { - try { - log.debug("Executing task implementation for task '{}'.", ti.getId()); - log.trace("Execution context before task execution: {}", pi.getExecutionContext().keySet()); - pendingReq = task.execute(pendingReq, pi.getExecutionContext()); - log.debug("Returned from execution of task '{}'.", ti.getId()); - log.trace("Execution context after task execution: {}", pi.getExecutionContext().keySet()); - - } catch (final Throwable t) { - throw new ProcessExecutionException("Error executing task '" + ti.getId() + "'.", t); - - } - - //check if process was cancelled dynamically by task - if (pi.getExecutionContext().isProcessCancelled()) { - log.debug("Processing task '{}' was cancelled by Task: '{}'.", pi.getId(), ti.getId()); - processFinishEvent(pi); - return; - - } - - } else { - log.debug("No task implementing class set."); - - } - } finally { - MDC.remove(MDC_CTX_TASK_NAME); - - } - - } else if (processNode instanceof EndEvent) { - processFinishEvent(pi); - return; - - } - - final ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContextImpl(pi); - - // traverse pointer - final Transition t = IterableUtils.find(processNode.getOutgoingTransitions(), new Predicate<Transition>() { - @Override - public boolean evaluate(Transition transition) { - if (transitionConditionExpressionEvaluator != null && transition.getConditionExpression() != null) { - log.trace("Evaluating transition expression '{}'.", transition.getConditionExpression()); - return transitionConditionExpressionEvaluator.evaluate(expressionContext, transition.getConditionExpression()); - } - return true; - } - }); - if (t == null) { - throw new ProcessExecutionException("No valid transition starting from process node '" + processNode.getId()+ "'."); - } - log.trace("Found suitable transition: {}", t); - // update pointer - log.trace("Shifting process token from '{}' to '{}'.", pi.getNextId(), t.getTo().getId()); - pi.setNextId(t.getTo().getId()); - - // inspect current task - if (t.getTo() instanceof TaskInfo && (((TaskInfo) t.getTo()).isAsync())) { - // immediately return in case of asynchonous task - log.debug("Suspending process instance '{}' for asynchronous task '{}'.", pi.getId(), t.getTo().getId()); - pi.setState(ProcessInstanceState.SUSPENDED); - return; - } - - // continue execution in case of StartEvent or Task - if (processNode instanceof StartEvent || processNode instanceof TaskInfo) { - execute(pi, pendingReq); - } - } - - @Override - public ProcessInstance getProcessInstance(String processInstanceId) { - - ProcessInstance processInstance; - try { - processInstance = loadProcessInstance(processInstanceId); - - } catch (final EAAFException e) { - throw new RuntimeException("The process instance '" + processInstanceId + "' could not be retrieved.", e); - } - - if (processInstance == null) { - throw new IllegalArgumentException("The process instance '" + processInstanceId + "' does not/no longer exist."); - } - - return processInstance; - } - - /** - * Persists a {@link ProcessInstance} to the database. - * @param processInstance The object to persist. - * @throws MOADatabaseException Thrown if an error occurs while accessing the database. - */ - private void saveOrUpdateProcessInstance(ProcessInstance processInstance) throws EAAFException { - final ProcessInstanceStore store = new ProcessInstanceStore(); - - final ExecutionContext ctx = processInstance.getExecutionContext(); - - final Map<String, Serializable> ctxData = new HashMap<String, Serializable>(); - for (final String key : ctx.keySet()) { - ctxData.put(key, ctx.get(key)); - } - store.setExecutionContextData(ctxData); - - store.setNextTaskId(processInstance.getNextId()); - store.setProcessDefinitionId(processInstance.getProcessDefinition().getId()); - - store.setProcessInstanceId(processInstance.getId()); - store.setProcessState(processInstance.getState()); - - piStoreDao.saveOrUpdate(store); - } - - /** - * Load a {@link ProcessInstance} with a certain id from the database. - * @param processInstanceId The process instance id - * @return The process instance corresponding to the id or {@code null} if no such object is found. - * @throws MOADatabaseException Thrown if an error occurs while accessing the database. - */ - private ProcessInstance loadProcessInstance(String processInstanceId) throws EAAFException { - - final ProcessInstanceStore piStore = piStoreDao.load(processInstanceId); - - if (piStore == null) { - return null; - } - - final ExecutionContext executionContext = new ExecutionContextImpl(piStore.getProcessInstanceId()); - - final Map<String, Serializable> executionContextData = piStore.getExecutionContextData(); - for (final String key : executionContextData.keySet()) { - executionContext.put(key, executionContextData.get(key)); - } - - final ProcessInstance pi = new ProcessInstance(processDefinitions.get(piStore.getProcessDefinitionId()), executionContext); - pi.setNextId(piStore.getNextTaskId()); - pi.setState(piStore.getProcessState()); - - return pi; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.process.ProcessEngine#deleteProcessInstance(java.lang.String) - */ - @Override - public void deleteProcessInstance(String processInstanceId) throws ProcessExecutionException { - if (StringUtils.isEmpty(processInstanceId)) { - throw new ProcessExecutionException("Unable to remove process instance: ProcessInstanceId is empty"); - - } - - try { - piStoreDao.remove(processInstanceId); - - } catch (final EAAFException e) { - throw new ProcessExecutionException("Unable to remove process instance.", e); - - } - - } - - /** - * Finish a process-flow and remove any process-flow related information - * - * @param pi - * @throws ProcessExecutionException - */ - private void processFinishEvent(ProcessInstance pi) throws ProcessExecutionException { - log.info("Finishing process instance '{}'.", pi.getId()); - - try { - piStoreDao.remove(pi.getId()); - - } catch (final EAAFException e) { - throw new ProcessExecutionException("Unable to remove process instance.", e); - - } - pi.setState(ProcessInstanceState.ENDED); - log.debug("Final process context: {}", pi.getExecutionContext().keySet()); - - } - - /** - * Perform some post-validation operations on process definition - * - * Like: check if all tasks that are defined are available on context - * - * @param pd - * @throws ProcessDefinitionParserException - */ - private void postValidationOfProcessDefintion(ProcessDefinition pd) throws ProcessDefinitionParserException{ - try { - for(final TaskInfo task : pd.getTaskInfos().values()) { - createTaskInstance(task); - } - - } catch (final ProcessExecutionException e) { - log.error("Post-validation of process definition: {} find an error: {}", pd.getId(), e.getMessage()); - throw new ProcessDefinitionParserException("Post-validation find an error in process definition:" + pd.getId(), e); - - } - } + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Autowired + ProcessInstanceStoreDao piStoreDao; + @Autowired + ApplicationContext context; + + private final ProcessDefinitionParser pdp = new ProcessDefinitionParser(); + + private final Map<String, ProcessDefinition> processDefinitions = new ConcurrentHashMap<>(); + + private static final String MDC_CTX_PI_NAME = "processInstanceId"; + private static final String MDC_CTX_TASK_NAME = "taskId"; + + private ExpressionEvaluator transitionConditionExpressionEvaluator; + + @Override + public void registerProcessDefinition(final ProcessDefinition processDefinition) { + log.info("Registering process definition '{}'.", processDefinition.getId()); + processDefinitions.put(processDefinition.getId(), processDefinition); + } + + @Override + public String registerProcessDefinition(final InputStream processDefinitionInputStream) + throws ProcessDefinitionParserException { + final ProcessDefinition pd = pdp.parse(processDefinitionInputStream); + + postValidationOfProcessDefintion(pd); + + registerProcessDefinition(pd); + return pd.getId(); + } + + /** + * Sets the process definitions. + * + * @param processDefinitions The process definitions. + * @throws IllegalArgumentException In case the process definitions contain + * definitions with the same identifier. + */ + public void setProcessDefinitions(final Iterable<ProcessDefinition> processDefinitions) { + this.processDefinitions.clear(); + for (final ProcessDefinition pd : processDefinitions) { + if (this.processDefinitions.containsKey(pd.getId())) { + throw new IllegalArgumentException( + "Duplicate process definition identifier '" + pd.getId() + "'."); + } + registerProcessDefinition(pd); + } + } + + /** + * Sets an expression evaluator that should be used to process transition + * condition expressions. + * + * @param transitionConditionExpressionEvaluator The expression evaluator. + */ + public void setTransitionConditionExpressionEvaluator( + final ExpressionEvaluator transitionConditionExpressionEvaluator) { + this.transitionConditionExpressionEvaluator = transitionConditionExpressionEvaluator; + } + + @Override + public String createProcessInstance(final String processDefinitionId, + final ExecutionContext executionContext) throws ProcessExecutionException { + // look for respective process definition + final ProcessDefinition pd = processDefinitions.get(processDefinitionId); + if (pd == null) { + throw new ProcessExecutionException( + "Unable to find process definition for process '" + processDefinitionId + "'."); + } + // create and keep process instance + final ProcessInstance pi = new ProcessInstance(pd, executionContext); + log.info("Creating process instance from process definition '{}': {}", processDefinitionId, + pi.getId()); + + try { + saveOrUpdateProcessInstance(pi); + + } catch (final EaafException e) { + throw new ProcessExecutionException("Unable to persist process instance.", e); + } + + return pi.getId(); + } + + @Override + public String createProcessInstance(final String processDefinitionId) + throws ProcessExecutionException { + return createProcessInstance(processDefinitionId, null); + } + + @Override + public void start(final IRequest pendingReq) throws ProcessExecutionException { + try { + if (StringUtils.isEmpty(pendingReq.getProcessInstanceId())) { + log.error("Pending-request with id:" + pendingReq.getPendingRequestId() + + " includes NO 'ProcessInstanceId'"); + throw new ProcessExecutionException("Pending-request with id:" + + pendingReq.getPendingRequestId() + " includes NO 'ProcessInstanceId'"); + } + + final ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId()); + + if (pi == null) { + throw new ProcessExecutionException( + "Process instance '" + pendingReq.getProcessInstanceId() + "' does not exist."); + + } + + MDC.put(MDC_CTX_PI_NAME, pi.getId()); + + if (!ProcessInstanceState.NOT_STARTED.equals(pi.getState())) { + throw new ProcessExecutionException("Process instance '" + pi.getId() + + "' has already been started (current state is " + pi.getState() + ")."); + } + log.info("Starting process instance '{}'.", pi.getId()); + // execute process + pi.setState(ProcessInstanceState.STARTED); + execute(pi, pendingReq); + + // store ProcessInstance if it is not already ended + if (!ProcessInstanceState.ENDED.equals(pi.getState())) { + saveOrUpdateProcessInstance(pi); + } + + } catch (final EaafException e) { + throw new ProcessExecutionException("Unable to load/save process instance.", e); + + } finally { + MDC.remove(MDC_CTX_PI_NAME); + } + } + + @Override + public void signal(final IRequest pendingReq) throws ProcessExecutionException { + + try { + if (StringUtils.isEmpty(pendingReq.getProcessInstanceId())) { + log.error("Pending-request with id:" + pendingReq.getPendingRequestId() + + " includes NO 'ProcessInstanceId'"); + throw new ProcessExecutionException("Pending-request with id:" + + pendingReq.getPendingRequestId() + " includes NO 'ProcessInstanceId'"); + } + + final ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId()); + + if (pi == null) { + throw new ProcessExecutionException( + "Process instance '" + pendingReq.getProcessInstanceId() + "' does not exist."); + + } + + MDC.put(MDC_CTX_PI_NAME, pi.getId()); + + if (!ProcessInstanceState.SUSPENDED.equals(pi.getState())) { + throw new ProcessExecutionException("Process instance '" + pi.getId() + + "' has not been suspended (current state is " + pi.getState() + ")."); + } + + log.debug("Waking up process instance '{}'.", pi.getId()); + pi.setState(ProcessInstanceState.STARTED); + + // put pending-request ID on execution-context because it could be changed + pi.getExecutionContext().put(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, + pendingReq.getPendingRequestId()); + + execute(pi, pendingReq); + + // store ProcessInstance if it is not already ended + if (!ProcessInstanceState.ENDED.equals(pi.getState())) { + saveOrUpdateProcessInstance(pi); + } + + } catch (final EaafException e) { + throw new ProcessExecutionException("Unable to load/save process instance.", e); + + } finally { + MDC.remove(MDC_CTX_PI_NAME); + } + } + + /** + * Instantiates a task implementation given by a {@link TaskInfo}. + * + * @param ti The task info. + * @return A Task implementation or {@code null} if the task info does not + * reference any task implementing classes. + * @throws ProcessExecutionException Thrown in case of error (when the + * referenced class does not implement + * {@link Task} for instance). + */ + private Task createTaskInstance(final TaskInfo ti) throws ProcessExecutionException { + final String clazz = StringUtils.trimToNull(ti.getTaskImplementingClass()); + Task task = null; + + if (clazz != null) { + log.debug("Instantiating task implementing class '{}'.", clazz); + Object instanceClass = null; + try { + instanceClass = context.getBean(clazz); + + } catch (final Exception e) { + throw new ProcessExecutionException( + "Unable to get class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); + + } + if (instanceClass == null || !(instanceClass instanceof Task)) { + throw new ProcessExecutionException("Class '" + clazz + "' associated with task '" + + ti.getId() + "' is not assignable to " + Task.class.getName() + "."); + + } + try { + task = (Task) instanceClass; + + } catch (final Exception e) { + throw new ProcessExecutionException("Unable to instantiate class '" + clazz + + "' associated with task '" + ti.getId() + "' .", e); + } + } + + return task; + } + + /** + * Starts/executes a given process instance. + * + * @param pi The process instance. + * @param pendingReq current pending request + * @throws ProcessExecutionException Thrown in case of error. + */ + private void execute(final ProcessInstance pi, IRequest pendingReq) + throws ProcessExecutionException { + if (ProcessInstanceState.ENDED.equals(pi.getState())) { + throw new ProcessExecutionException( + "Process for instance '" + pi.getId() + "' has already been ended."); + } + final ProcessDefinition pd = pi.getProcessDefinition(); + final ProcessNode processNode = pd.getProcessNode(pi.getNextId()); + log.debug("Processing node '{}'.", processNode.getId()); + + // distinguish process node types StartEvent, TaskInfo and EndEvent + + if (processNode instanceof TaskInfo) { + // TaskInfo types need to be executed + final TaskInfo ti = (TaskInfo) processNode; + MDC.put(MDC_CTX_TASK_NAME, ti.getId()); + try { + log.debug("Processing task '{}'.", ti.getId()); + final Task task = createTaskInstance(ti); + if (task != null) { + try { + log.debug("Executing task implementation for task '{}'.", ti.getId()); + log.trace("Execution context before task execution: {}", + pi.getExecutionContext().keySet()); + pendingReq = task.execute(pendingReq, pi.getExecutionContext()); + log.debug("Returned from execution of task '{}'.", ti.getId()); + log.trace("Execution context after task execution: {}", + pi.getExecutionContext().keySet()); + + } catch (final Throwable t) { + throw new ProcessExecutionException("Error executing task '" + ti.getId() + "'.", t); + + } + + // check if process was cancelled dynamically by task + if (pi.getExecutionContext().isProcessCancelled()) { + log.debug("Processing task '{}' was cancelled by Task: '{}'.", pi.getId(), ti.getId()); + processFinishEvent(pi); + return; + + } + + } else { + log.debug("No task implementing class set."); + + } + } finally { + MDC.remove(MDC_CTX_TASK_NAME); + + } + + } else if (processNode instanceof EndEvent) { + processFinishEvent(pi); + return; + + } + + final ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContextImpl(pi); + + // traverse pointer + final Transition t = IterableUtils.find(processNode.getOutgoingTransitions(), transition -> { + if (transitionConditionExpressionEvaluator != null + && transition.getConditionExpression() != null) { + log.trace("Evaluating transition expression '{}'.", transition.getConditionExpression()); + return transitionConditionExpressionEvaluator.evaluate(expressionContext, + transition.getConditionExpression()); + } + return true; + }); + if (t == null) { + throw new ProcessExecutionException( + "No valid transition starting from process node '" + processNode.getId() + "'."); + } + log.trace("Found suitable transition: {}", t); + // update pointer + log.trace("Shifting process token from '{}' to '{}'.", pi.getNextId(), t.getTo().getId()); + pi.setNextId(t.getTo().getId()); + + // inspect current task + if (t.getTo() instanceof TaskInfo && ((TaskInfo) t.getTo()).isAsync()) { + // immediately return in case of asynchonous task + log.debug("Suspending process instance '{}' for asynchronous task '{}'.", pi.getId(), + t.getTo().getId()); + pi.setState(ProcessInstanceState.SUSPENDED); + return; + } + + // continue execution in case of StartEvent or Task + if (processNode instanceof StartEvent || processNode instanceof TaskInfo) { + execute(pi, pendingReq); + } + } + + @Override + public ProcessInstance getProcessInstance(final String processInstanceId) { + + ProcessInstance processInstance; + try { + processInstance = loadProcessInstance(processInstanceId); + + } catch (final EaafException e) { + throw new RuntimeException( + "The process instance '" + processInstanceId + "' could not be retrieved.", e); + } + + if (processInstance == null) { + throw new IllegalArgumentException( + "The process instance '" + processInstanceId + "' does not/no longer exist."); + } + + return processInstance; + } + + /** + * Persists a {@link ProcessInstance} to the database. + * + * @param processInstance The object to persist. + * @throws MOADatabaseException Thrown if an error occurs while accessing the + * database. + */ + private void saveOrUpdateProcessInstance(final ProcessInstance processInstance) + throws EaafException { + final ProcessInstanceStore store = new ProcessInstanceStore(); + + final ExecutionContext ctx = processInstance.getExecutionContext(); + + final Map<String, Serializable> ctxData = new HashMap<>(); + for (final String key : ctx.keySet()) { + ctxData.put(key, ctx.get(key)); + } + store.setExecutionContextData(ctxData); + + store.setNextTaskId(processInstance.getNextId()); + store.setProcessDefinitionId(processInstance.getProcessDefinition().getId()); + + store.setProcessInstanceId(processInstance.getId()); + store.setProcessState(processInstance.getState()); + + piStoreDao.saveOrUpdate(store); + } + + /** + * Load a {@link ProcessInstance} with a certain id from the database. + * + * @param processInstanceId The process instance id + * @return The process instance corresponding to the id or {@code null} if no + * such object is found. + * @throws MOADatabaseException Thrown if an error occurs while accessing the + * database. + */ + private ProcessInstance loadProcessInstance(final String processInstanceId) throws EaafException { + + final ProcessInstanceStore piStore = piStoreDao.load(processInstanceId); + + if (piStore == null) { + return null; + } + + final ExecutionContext executionContext = + new ExecutionContextImpl(piStore.getProcessInstanceId()); + + final Map<String, Serializable> executionContextData = piStore.getExecutionContextData(); + for (final Entry<String, Serializable> el : executionContextData.entrySet()) { + executionContext.put(el.getKey(), el.getValue()); + } + + final ProcessInstance pi = new ProcessInstance( + processDefinitions.get(piStore.getProcessDefinitionId()), executionContext); + pi.setNextId(piStore.getNextTaskId()); + pi.setState(piStore.getProcessState()); + + return pi; + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.process.ProcessEngine#deleteProcessInstance(java. + * lang.String) + */ + @Override + public void deleteProcessInstance(final String processInstanceId) + throws ProcessExecutionException { + if (StringUtils.isEmpty(processInstanceId)) { + throw new ProcessExecutionException( + "Unable to remove process instance: ProcessInstanceId is empty"); + + } + + try { + piStoreDao.remove(processInstanceId); + + } catch (final EaafException e) { + throw new ProcessExecutionException("Unable to remove process instance.", e); + + } + + } + + /** + * Finish a process-flow and remove any process-flow related information. + * + * @param pi current process instance + * @throws ProcessExecutionException In case of an process error + */ + private void processFinishEvent(final ProcessInstance pi) throws ProcessExecutionException { + log.info("Finishing process instance '{}'.", pi.getId()); + + try { + piStoreDao.remove(pi.getId()); + + } catch (final EaafException e) { + throw new ProcessExecutionException("Unable to remove process instance.", e); + + } + pi.setState(ProcessInstanceState.ENDED); + log.debug("Final process context: {}", pi.getExecutionContext().keySet()); + + } + + /** + * Perform some post-validation operations on process definition. + * + * <p> + * Like: check if all tasks that are defined are available on context + * </p> + * + * @param pd current process definition + * @throws ProcessDefinitionParserException In case of a parser error + */ + private void postValidationOfProcessDefintion(final ProcessDefinition pd) + throws ProcessDefinitionParserException { + try { + for (final TaskInfo task : pd.getTaskInfos().values()) { + createTaskInstance(task); + } + + } catch (final ProcessExecutionException e) { + log.error("Post-validation of process definition: {} find an error: {}", pd.getId(), + e.getMessage()); + throw new ProcessDefinitionParserException( + "Post-validation find an error in process definition:" + pd.getId(), e); + + } + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstance.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstance.java index 6db1dc7d..f3ec6b2d 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstance.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstance.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process; import java.io.Serializable; @@ -39,152 +32,156 @@ import at.gv.egiz.eaaf.core.impl.idp.process.model.ProcessDefinition; import at.gv.egiz.eaaf.core.impl.idp.process.support.SecureRandomHolder; /** - * Represents a process being executed. The process instance provides information about the process and its state. - * + * Represents a process being executed. The process instance provides + * information about the process and its state. + * * @author tknall - * + * */ public class ProcessInstance implements Serializable { - private static final long serialVersionUID = 1L; - private static final int RND_ID_LENGTH = 22; - - private final ProcessDefinition processDefinition; - private String nextId; - private Date lru; - private final ExecutionContext executionContext; - private ProcessInstanceState state = ProcessInstanceState.NOT_STARTED; - - private final Logger log = LoggerFactory.getLogger(getClass()); - - /** - * Creates a new process instance, based on a given process definition and a - * given execution context. If the given execution context is {@code null} a new execution context will be created.<p/> - * The process instance id of the execution context will be newly generated if it is {@code null} in the execution context. - * - * @param processDefinition - * The process definition. - * @param executionContext - * The execution context (may be {@code null}). If {@code null} a new execution context will be created internally. - */ - ProcessInstance(ProcessDefinition processDefinition, ExecutionContext executionContext) { - this.processDefinition = processDefinition; - nextId = processDefinition.getStartEvent().getId(); - if (executionContext == null) { - executionContext = new ExecutionContextImpl(); - } - if (executionContext.getProcessInstanceId() == null) { - final String pdIdLocalPart = RandomStringUtils.random(RND_ID_LENGTH, 0, 0, true, true, null, - SecureRandomHolder.getInstance()); - executionContext.setProcessInstanceId(this.processDefinition.getId() + "-" + pdIdLocalPart); - } else { - log.debug("Using process instance id from execution context."); - } - log.debug("Creating process instance with id '{}'.", executionContext.getProcessInstanceId()); - this.executionContext = executionContext; - touch(); - } - - /** - * Returns the underlying process definition. - * - * @return The underlying process definition. - */ - ProcessDefinition getProcessDefinition() { - touch(); - return processDefinition; - } - - /** - * Returns the id of the process node to be executed next. - * - * @return The process node pointer indicating the process node to be executed next. - */ - public String getNextId() { - touch(); - return nextId; - } - - /** - * Sets the internal pointer to the process node to be executed next. - * - * @param nextId - * The process node id to be executed next. - */ - void setNextId(String nextId) { - touch(); - this.nextId = nextId; - } - - /** - * Returns the current state of the process instance. - * - * @return The current state. - */ - public ProcessInstanceState getState() { - touch(); - return state; - } - - /** - * Sets the current state of the process instance. - * - * @param state - * The current state. - */ - void setState(ProcessInstanceState state) { - touch(); - this.state = state; - } - - public String getId() { - touch(); - return executionContext.getProcessInstanceId(); - } - - /** - * Updates the last recently used date of the process instance. - */ - private void touch() { - lru = new Date(); - } - - /** - * Returns the date the process instance has been accessed last. - * - * @return The last recently used date. - */ - Date getLru() { - return lru; - } - - /** - * Returns the associated execution context. - * @return The execution context (never {@code null}). - */ - public ExecutionContext getExecutionContext() { - touch(); - return executionContext; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("ProcessInstance ["); - builder.append("id=").append(executionContext.getProcessInstanceId()); - builder.append(", idle since=").append( - DurationFormatUtils.formatDurationWords(new Date().getTime() - this.lru.getTime(), true, true)); - if (processDefinition != null) { - builder.append(", processDefinition.id="); - builder.append(processDefinition.getId()); - } - if (nextId != null) { - builder.append(", nextId="); - builder.append(nextId); - } - builder.append(", executionContext=").append(executionContext); - builder.append("]"); - return builder.toString(); - } + private static final long serialVersionUID = 1L; + private static final int RND_ID_LENGTH = 22; + + private final ProcessDefinition processDefinition; + private String nextId; + private Date lru; + private final ExecutionContext executionContext; + private ProcessInstanceState state = ProcessInstanceState.NOT_STARTED; + + /** + * Creates a new process instance, based on a given process definition and a + * given execution context. If the given execution context is {@code null} a new + * execution context will be created. + * <p/> + * The process instance id of the execution context will be newly generated if + * it is {@code null} in the execution context. + * + * @param processDefinition The process definition. + * @param executionContext The execution context (may be {@code null}). If + * {@code null} a new execution context will be created + * internally. + */ + ProcessInstance(final ProcessDefinition processDefinition, ExecutionContext executionContext) { + final Logger log = LoggerFactory.getLogger(getClass()); + + this.processDefinition = processDefinition; + nextId = processDefinition.getStartEvent().getId(); + if (executionContext == null) { + executionContext = new ExecutionContextImpl(); + } + if (executionContext.getProcessInstanceId() == null) { + final String pdIdLocalPart = RandomStringUtils.random(RND_ID_LENGTH, 0, 0, true, true, null, + SecureRandomHolder.getInstance()); + executionContext.setProcessInstanceId(this.processDefinition.getId() + "-" + pdIdLocalPart); + } else { + log.debug("Using process instance id from execution context."); + } + log.debug("Creating process instance with id '{}'.", executionContext.getProcessInstanceId()); + this.executionContext = executionContext; + touch(); + } + + /** + * Returns the underlying process definition. + * + * @return The underlying process definition. + */ + ProcessDefinition getProcessDefinition() { + touch(); + return processDefinition; + } + + /** + * Returns the id of the process node to be executed next. + * + * @return The process node pointer indicating the process node to be executed + * next. + */ + public String getNextId() { + touch(); + return nextId; + } + + /** + * Sets the internal pointer to the process node to be executed next. + * + * @param nextId The process node id to be executed next. + */ + void setNextId(final String nextId) { + touch(); + this.nextId = nextId; + } + + /** + * Returns the current state of the process instance. + * + * @return The current state. + */ + public ProcessInstanceState getState() { + touch(); + return state; + } + + /** + * Sets the current state of the process instance. + * + * @param state The current state. + */ + void setState(final ProcessInstanceState state) { + touch(); + this.state = state; + } + + public String getId() { + touch(); + return executionContext.getProcessInstanceId(); + } + + /** + * Updates the last recently used date of the process instance. + */ + private void touch() { + lru = new Date(); + } + + /** + * Returns the date the process instance has been accessed last. + * + * @return The last recently used date. + */ + Date getLru() { + return lru; + } + + /** + * Returns the associated execution context. + * + * @return The execution context (never {@code null}). + */ + public ExecutionContext getExecutionContext() { + touch(); + return executionContext; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("ProcessInstance ["); + builder.append("id=").append(executionContext.getProcessInstanceId()); + builder.append(", idle since=").append(DurationFormatUtils + .formatDurationWords(new Date().getTime() - this.lru.getTime(), true, true)); + if (processDefinition != null) { + builder.append(", processDefinition.id="); + builder.append(processDefinition.getId()); + } + if (nextId != null) { + builder.append(", nextId="); + builder.append(nextId); + } + builder.append(", executionContext=").append(executionContext); + builder.append("]"); + return builder.toString(); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstanceState.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstanceState.java index 1abf5b86..f2353869 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstanceState.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstanceState.java @@ -1,56 +1,52 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process; /** * Represents a certain process instance state. + * * @author tknall * */ public enum ProcessInstanceState { - - /** - * Indicates that the process with this process instance has not yet been started. - */ - NOT_STARTED, - - /** - * Indicates that the process is currently running. - */ - STARTED, - - /** - * Indicates that the process has been suspended until being waken up by someonce calling {@code signal}. - */ - SUSPENDED, - - /** - * Indicates that the process has been completed. - */ - ENDED + + /** + * Indicates that the process with this process instance has not yet been + * started. + */ + NOT_STARTED, + + /** + * Indicates that the process is currently running. + */ + STARTED, + + /** + * Indicates that the process has been suspended until being waken up by + * someonce calling {@code signal}. + */ + SUSPENDED, + + /** + * Indicates that the process has been completed. + */ + ENDED } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStore.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStore.java index 0fee29e5..07d44f36 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStore.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStore.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.dao; import java.io.Serializable; @@ -31,69 +24,69 @@ import java.util.Map; import at.gv.egiz.eaaf.core.impl.idp.process.ProcessInstanceState; -public class ProcessInstanceStore implements Serializable{ +public class ProcessInstanceStore implements Serializable { + + private static final long serialVersionUID = -6147519767313903808L; + + /** + * A process instance identifier qualifies as natural primary key by satisfying + * these requirements. ("unique, constant, required"): + * <ul> + * <li>unique value</li> + * <li>never changes (immutable)</li> + * <li>never {@code null}</li> + * </ul> + */ - private static final long serialVersionUID = -6147519767313903808L; + private String processInstanceId; - /** - * A process instance identifier qualifies as natural primary key by satisfying these requirements - * ("unique, constant, required"): - * <ul> - * <li>unique value</li> - * <li>never changes (immutable)</li> - * <li>never {@code null}</li> - * </ul> - */ + private String processDefinitionId; - private String processInstanceId; + private String nextTaskId; - private String processDefinitionId; + private ProcessInstanceState processState; - private String nextTaskId; + private Map<String, Serializable> executionContextData; - private ProcessInstanceState processState; - - private Map<String, Serializable> executionContextData; - - public String getProcessInstanceId() { - return processInstanceId; - } + public String getProcessInstanceId() { + return processInstanceId; + } - public String getProcessDefinitionId() { - return processDefinitionId; - } + public String getProcessDefinitionId() { + return processDefinitionId; + } - public String getNextTaskId() { - return nextTaskId; - } + public String getNextTaskId() { + return nextTaskId; + } - public ProcessInstanceState getProcessState() { - return processState; - } + public ProcessInstanceState getProcessState() { + return processState; + } - @SuppressWarnings("unchecked") - public Map<String, Serializable> getExecutionContextData() { - return executionContextData; - } + @SuppressWarnings("unchecked") + public Map<String, Serializable> getExecutionContextData() { + return executionContextData; + } - public void setProcessInstanceId(String processInstanceId) { - this.processInstanceId = processInstanceId; - } + public void setProcessInstanceId(final String processInstanceId) { + this.processInstanceId = processInstanceId; + } - public void setProcessDefinitionId(String processDefinitionId) { - this.processDefinitionId = processDefinitionId; - } + public void setProcessDefinitionId(final String processDefinitionId) { + this.processDefinitionId = processDefinitionId; + } - public void setNextTaskId(String nextTaskId) { - this.nextTaskId = nextTaskId; - } + public void setNextTaskId(final String nextTaskId) { + this.nextTaskId = nextTaskId; + } - public void setProcessState(ProcessInstanceState processState) { - this.processState = processState; - } + public void setProcessState(final ProcessInstanceState processState) { + this.processState = processState; + } - public void setExecutionContextData(Map<String, Serializable> executionContextData) { - this.executionContextData = executionContextData; - } + public void setExecutionContextData(final Map<String, Serializable> executionContextData) { + this.executionContextData = executionContextData; + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDAOImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDAOImpl.java deleted file mode 100644 index 681c9707..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDAOImpl.java +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.process.dao; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import at.gv.egiz.eaaf.core.api.idp.process.ProcessInstanceStoreDAO; -import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; - -/** - * Database backed implementation of the {@link ProcessInstanceStoreDAO} - * interface. - */ -@Service("ProcessInstanceStoreage") -public class ProcessInstanceStoreDAOImpl implements ProcessInstanceStoreDAO { - - private Logger log = LoggerFactory.getLogger(getClass()); - - @Autowired ITransactionStorage transactionStorage; - - @Override - public void saveOrUpdate(ProcessInstanceStore pIStore) throws EAAFException { - try { - transactionStorage.put(pIStore.getProcessInstanceId(), pIStore, -1); - log.debug("Store process instance with='{}' in the database.", pIStore.getProcessInstanceId()); - - } catch (EAAFException e) { - log.warn("ProcessInstanceStore could not be persisted to the database."); - throw e; - } - } - - @Override - public ProcessInstanceStore load(String processInstanceId) throws EAAFException { - log.debug("Retrieve the ProcessInstanceStore for id='{}' from the database.", processInstanceId); - ProcessInstanceStore result = null; - try { - result = transactionStorage.get(processInstanceId, ProcessInstanceStore.class); - - } catch (Exception e) { - log.error("There are multiple persisted processes with the same process instance id '{}'", - processInstanceId); - - throw e; - } - - if (result != null) { - log.debug("Found process instance store for instance '{}'.", processInstanceId); - - } else { - log.debug("Unable to find process instance store for instance '{}'.", processInstanceId); - - } - - return result; - } - - @Override - public void remove(String processInstanceId) throws EAAFException { - - log.debug("Delete the ProcessInstanceStore for id='{}' from the database.", processInstanceId); - - if (transactionStorage.containsKey(processInstanceId)) - transactionStorage.remove(processInstanceId); - else - log.trace("ProcessInstanceStore for id='{}' was not found and could therefore not be deleted.", processInstanceId); - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDaoImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDaoImpl.java new file mode 100644 index 00000000..cca8872f --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDaoImpl.java @@ -0,0 +1,96 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.idp.process.dao; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.idp.process.ProcessInstanceStoreDao; +import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; +import at.gv.egiz.eaaf.core.exceptions.EaafException; + +/** + * Database backed implementation of the {@link ProcessInstanceStoreDao} + * interface. + */ +@Service("ProcessInstanceStoreage") +public class ProcessInstanceStoreDaoImpl implements ProcessInstanceStoreDao { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Autowired + ITransactionStorage transactionStorage; + + @Override + public void saveOrUpdate(final ProcessInstanceStore piStore) throws EaafException { + try { + transactionStorage.put(piStore.getProcessInstanceId(), piStore, -1); + log.debug("Store process instance with='{}' in the database.", + piStore.getProcessInstanceId()); + + } catch (final EaafException e) { + log.warn("ProcessInstanceStore could not be persisted to the database."); + throw e; + } + } + + @Override + public ProcessInstanceStore load(final String processInstanceId) throws EaafException { + log.debug("Retrieve the ProcessInstanceStore for id='{}' from the database.", + processInstanceId); + ProcessInstanceStore result = null; + try { + result = transactionStorage.get(processInstanceId, ProcessInstanceStore.class); + + } catch (final Exception e) { + log.error("There are multiple persisted processes with the same process instance id '{}'", + processInstanceId); + + throw e; + } + + if (result != null) { + log.debug("Found process instance store for instance '{}'.", processInstanceId); + + } else { + log.debug("Unable to find process instance store for instance '{}'.", processInstanceId); + + } + + return result; + } + + @Override + public void remove(final String processInstanceId) throws EaafException { + + log.debug("Delete the ProcessInstanceStore for id='{}' from the database.", processInstanceId); + + if (transactionStorage.containsKey(processInstanceId)) { + transactionStorage.remove(processInstanceId); + } else { + log.trace( + "ProcessInstanceStore for id='{}' was not found and could therefore not be deleted.", + processInstanceId); + } + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/EndEvent.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/EndEvent.java index 8657d0dc..ac7406ae 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/EndEvent.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/EndEvent.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.model; import java.io.Serializable; @@ -31,38 +24,39 @@ import java.io.Serializable; import org.apache.commons.collections4.CollectionUtils; /** - * Represents an end event. Process execution terminates when an end event is reached. - * + * Represents an end event. Process execution terminates when an end event is + * reached. + * * @author tknall */ public class EndEvent extends ProcessNode implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("EndEvent ["); - if (getId() != null) { - builder.append("id="); - builder.append(getId()); - } - if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("incomingTransitions="); - builder.append(getIncomingTransitions()); - } - if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("outgoingTransitions="); - builder.append(getOutgoingTransitions()); - } - builder.append("]"); - return builder.toString(); - } + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("EndEvent ["); + if (getId() != null) { + builder.append("id="); + builder.append(getId()); + } + if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("incomingTransitions="); + builder.append(getIncomingTransitions()); + } + if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("outgoingTransitions="); + builder.append(getOutgoingTransitions()); + } + builder.append("]"); + return builder.toString(); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/ProcessDefinition.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/ProcessDefinition.java index b7caef7a..39adda69 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/ProcessDefinition.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/ProcessDefinition.java @@ -1,31 +1,25 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.model; +import java.io.Serializable; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; @@ -33,152 +27,153 @@ import java.util.Objects; import at.gv.egiz.eaaf.core.impl.idp.process.ProcessDefinitionParser; /** - * Represents a single process definition containing + * Represents a single process definition containing. * <ul> * <li>a {@link StartEvent},</li> * <li>one or more {@linkplain TaskInfo Tasks},</li> * <li>one or more {@linkplain EndEvent EndEvents} and</li> - * <li>some {@linkplain Transition Transitions} linking StartEvents, Tasks and EndEvents. + * <li>some {@linkplain Transition Transitions} linking StartEvents, Tasks and + * EndEvents. * </ul> - * + * * @author tknall - * + * */ -public class ProcessDefinition { - - private String id; - private StartEvent startEvent; - private Map<String, TaskInfo> taskInfos = new LinkedHashMap<>(); - private Map<String, EndEvent> endEvents = new LinkedHashMap<>(); - - /** - * Returns the unique identifier of the process definition. - * - * @return The unique identifier (never {@code null} if process definition comes from - * {@link ProcessDefinitionParser}). - */ - public String getId() { - return id; - } - - /** - * Sets the unique identifier of the process definition. - * - * @param id - * The unique identifier. - */ - public void setId(String id) { - this.id = id; - } - - /** - * Returns the start event of the process definition. - * - * @return The start event (never {@code null} if process definition comes from {@link ProcessDefinitionParser}). - */ - public StartEvent getStartEvent() { - return startEvent; - } - - /** - * Sets the start event of the process definition. - * - * @param startEvent - * The start event. - */ - public void setStartEvent(StartEvent startEvent) { - this.startEvent = startEvent; - } - - /** - * Returns a map containing the tasks of the process definition. - * - * @return The tasks (map is never {@code null} if process definition comes from {@link ProcessDefinitionParser}). - */ - public Map<String, TaskInfo> getTaskInfos() { - return taskInfos; - } - - /** - * Sets the map containing the tasks. - * - * @param taskInfos - * The map containing the tasks. - */ - public void setTaskInfos(Map<String, TaskInfo> taskInfos) { - this.taskInfos = taskInfos; - } - - /** - * Returns a map containing the end events of the process description. - * - * @return The map containing the end events (map is never {@code null} if process definition comes from - * {@link ProcessDefinitionParser}). - */ - public Map<String, EndEvent> getEndEvents() { - return endEvents; - } - - /** - * Sets a map containing the end events of the process description. - * - * @param endEvents - * The map containing the end events. - */ - public void setEndEvents(Map<String, EndEvent> endEvents) { - this.endEvents = endEvents; - } - - /** - * Returns the process node associated with the given {@code id}. - * - * @param id - * The identifier of the process node. - * @return The process node (may be {code null} when no process node with the given {@code id} exists). - */ - public ProcessNode getProcessNode(String id) { - Objects.requireNonNull(id, "Identifier must not be null."); - if (startEvent != null && id.equals(startEvent.getId())) { - return startEvent; - } - TaskInfo task = taskInfos.get(id); - if (task != null) { - return task; - } - return endEvents.get(id); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - if (id != null) { - builder.append("id="); - builder.append(id); - } - if (startEvent != null) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("startEvent="); - builder.append(startEvent); - } - if (taskInfos != null && !taskInfos.isEmpty()) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("tasksInfos="); - builder.append(taskInfos.values()); - } - if (endEvents != null && !endEvents.isEmpty()) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("endEvents="); - builder.append(endEvents.values()); - } - builder.insert(0, "ProcessDefinition ["); - builder.append("]"); - return builder.toString(); - } +public class ProcessDefinition implements Serializable { + + private static final long serialVersionUID = 7896697967510445442L; + + private String id; + private StartEvent startEvent; + private Map<String, TaskInfo> taskInfos = new LinkedHashMap<>(); + private Map<String, EndEvent> endEvents = new LinkedHashMap<>(); + + /** + * Returns the unique identifier of the process definition. + * + * @return The unique identifier (never {@code null} if process definition comes + * from {@link ProcessDefinitionParser}). + */ + public String getId() { + return id; + } + + /** + * Sets the unique identifier of the process definition. + * + * @param id The unique identifier. + */ + public void setId(final String id) { + this.id = id; + } + + /** + * Returns the start event of the process definition. + * + * @return The start event (never {@code null} if process definition comes from + * {@link ProcessDefinitionParser}). + */ + public StartEvent getStartEvent() { + return startEvent; + } + + /** + * Sets the start event of the process definition. + * + * @param startEvent The start event. + */ + public void setStartEvent(final StartEvent startEvent) { + this.startEvent = startEvent; + } + + /** + * Returns a map containing the tasks of the process definition. + * + * @return The tasks (map is never {@code null} if process definition comes from + * {@link ProcessDefinitionParser}). + */ + public Map<String, TaskInfo> getTaskInfos() { + return taskInfos; + } + + /** + * Sets the map containing the tasks. + * + * @param taskInfos The map containing the tasks. + */ + public void setTaskInfos(final Map<String, TaskInfo> taskInfos) { + this.taskInfos = taskInfos; + } + + /** + * Returns a map containing the end events of the process description. + * + * @return The map containing the end events (map is never {@code null} if + * process definition comes from {@link ProcessDefinitionParser}). + */ + public Map<String, EndEvent> getEndEvents() { + return endEvents; + } + + /** + * Sets a map containing the end events of the process description. + * + * @param endEvents The map containing the end events. + */ + public void setEndEvents(final Map<String, EndEvent> endEvents) { + this.endEvents = endEvents; + } + + /** + * Returns the process node associated with the given {@code id}. + * + * @param id The identifier of the process node. + * @return The process node (may be {code null} when no process node with the + * given {@code id} exists). + */ + public ProcessNode getProcessNode(final String id) { + Objects.requireNonNull(id, "Identifier must not be null."); + if (startEvent != null && id.equals(startEvent.getId())) { + return startEvent; + } + final TaskInfo task = taskInfos.get(id); + if (task != null) { + return task; + } + return endEvents.get(id); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + if (id != null) { + builder.append("id="); + builder.append(id); + } + if (startEvent != null) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("startEvent="); + builder.append(startEvent); + } + if (taskInfos != null && !taskInfos.isEmpty()) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("tasksInfos="); + builder.append(taskInfos.values()); + } + if (endEvents != null && !endEvents.isEmpty()) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("endEvents="); + builder.append(endEvents.values()); + } + builder.insert(0, "ProcessDefinition ["); + builder.append("]"); + return builder.toString(); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/ProcessNode.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/ProcessNode.java index 7964fa47..46f086f9 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/ProcessNode.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/ProcessNode.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.model; import java.util.ArrayList; @@ -32,64 +25,75 @@ import java.util.List; import at.gv.egiz.eaaf.core.impl.idp.process.ProcessDefinitionParser; /** - * Represents a {@link StartEvent}, an {@link EndEvent} or a {@linkplain TaskInfo Task}. + * Represents a {@link StartEvent}, an {@link EndEvent} or a + * {@linkplain TaskInfo Task}. + * * @author tknall * */ public abstract class ProcessNode { - private String id; - private List<Transition> outgoingTransitions = new ArrayList<>(); - private List<Transition> incomingTransitions = new ArrayList<>(); + private String id; + private List<Transition> outgoingTransitions = new ArrayList<>(); + private List<Transition> incomingTransitions = new ArrayList<>(); + + /** + * Returns the unique identifier of the process node. + * + * @return The unique identifier (never {@code null} if process node comes from + * a process definition from {@link ProcessDefinitionParser}). + */ + public String getId() { + return id; + } - /** - * Returns the unique identifier of the process node. - * - * @return The unique identifier (never {@code null} if process node comes from a process definition from - * {@link ProcessDefinitionParser}). - */ - public String getId() { - return id; - } + /** + * Sets the unique identifier of the process node. + * + * @param id The unique identifier. + */ + public void setId(final String id) { + this.id = id; + } - /** - * Sets the unique identifier of the process node. - * @param id The unique identifier. - */ - public void setId(String id) { - this.id = id; - } + /** + * Returns a list of transitions pointing from this process node to another one. + * + * @return A list of transitions (never {@code null} if process node comes from + * a process definition from {@link ProcessDefinitionParser}). + */ + public List<Transition> getOutgoingTransitions() { + return outgoingTransitions; + } - /** - * Returns a list of transitions pointing from this process node to another one. - * @return A list of transitions (never {@code null} if process node comes from a process definition from {@link ProcessDefinitionParser}). - */ - public List<Transition> getOutgoingTransitions() { - return outgoingTransitions; - } + /** + * Sets the list of transitions pointing from this process node to another one. + * + * @param outgoingTransitions The list of transitions originating from this + * process node. + */ + public void setOutgoingTransitions(final List<Transition> outgoingTransitions) { + this.outgoingTransitions = outgoingTransitions; + } - /** - * Sets the list of transitions pointing from this process node to another one. - * @param outgoingTransitions The list of transitions originating from this process node. - */ - public void setOutgoingTransitions(List<Transition> outgoingTransitions) { - this.outgoingTransitions = outgoingTransitions; - } + /** + * Returns a list of transitions pointing from another process node to this one. + * + * @return A list of transitions (never {@code null} if process node comes from + * a process definition from {@link ProcessDefinitionParser}). + */ + public List<Transition> getIncomingTransitions() { + return incomingTransitions; + } - /** - * Returns a list of transitions pointing from another process node to this one. - * @return A list of transitions (never {@code null} if process node comes from a process definition from {@link ProcessDefinitionParser}). - */ - public List<Transition> getIncomingTransitions() { - return incomingTransitions; - } + /** + * Sets the list of transitions pointing from another process node to this one. + * + * @param incomingTransitions A list of transitions pointing to this process + * node. + */ + public void setIncomingTransitions(final List<Transition> incomingTransitions) { + this.incomingTransitions = incomingTransitions; + } - /** - * Sets the list of transitions pointing from another process node to this one. - * @param incomingTransitions A list of transitions pointing to this process node. - */ - public void setIncomingTransitions(List<Transition> incomingTransitions) { - this.incomingTransitions = incomingTransitions; - } - } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/StartEvent.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/StartEvent.java index 8e358b69..ef6bc7ef 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/StartEvent.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/StartEvent.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.model; import java.io.Serializable; @@ -31,41 +24,41 @@ import java.io.Serializable; import org.apache.commons.collections4.CollectionUtils; /** - * Represents a start event. Each process description contains a single start event. Process execution starts with a - * start event. - * + * Represents a start event. Each process description contains a single start + * event. Process execution starts with a start event. + * * @author tknall - * + * */ public class StartEvent extends ProcessNode implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("StartEvent ["); - if (getId() != null) { - builder.append("id="); - builder.append(getId()); - } - if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("incomingTransitions="); - builder.append(getIncomingTransitions()); - } - if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("outgoingTransitions="); + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("StartEvent ["); + if (getId() != null) { + builder.append("id="); + builder.append(getId()); + } + if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("incomingTransitions="); + builder.append(getIncomingTransitions()); + } + if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("outgoingTransitions="); - builder.append(getOutgoingTransitions()); - } - builder.append("]"); - return builder.toString(); - } + builder.append(getOutgoingTransitions()); + } + builder.append("]"); + return builder.toString(); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/TaskInfo.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/TaskInfo.java index b98045c5..c8eea1bb 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/TaskInfo.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/TaskInfo.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ + package at.gv.egiz.eaaf.core.impl.idp.process.model; import java.io.Serializable; @@ -33,88 +26,98 @@ import org.apache.commons.collections4.CollectionUtils; import at.gv.egiz.eaaf.core.api.idp.process.Task; /** - * Represents information about a single task to be performed upon process execution. + * Represents information about a single task to be performed upon process + * execution. + * * @author tknall * */ public class TaskInfo extends ProcessNode implements Serializable { - private static final long serialVersionUID = 1L; - private static final boolean DEFAULT_ASYNC = false; - - private String taskImplementingClass; - private boolean async = DEFAULT_ASYNC; - - /** - * Determines if the task is marked asynchronous ({@code true}) or synchronous ({@code false}). - * @return A flag indicating if the task should be executed asynchronously or synchronously. (Default: {@code false}) - */ - public boolean isAsync() { - return async; - } + private static final long serialVersionUID = 1L; + private static final boolean DEFAULT_ASYNC = false; + + private String taskImplementingClass; + private boolean async = DEFAULT_ASYNC; + + /** + * Determines if the task is marked asynchronous ({@code true}) or synchronous + * ({@code false}). + * + * @return A flag indicating if the task should be executed asynchronously or + * synchronously. (Default: {@code false}) + */ + public boolean isAsync() { + return async; + } - /** - * Marks a task to executed asynchronously ({@code true}) or synchronously ({@code false}). - * @param async The flag. - */ - public void setAsync(boolean async) { - this.async = async; - } + /** + * Marks a task to executed asynchronously ({@code true}) or synchronously + * ({@code false}). + * + * @param async The flag. + */ + public void setAsync(final boolean async) { + this.async = async; + } - /** - * Returns the class that implements the actual task (must implement {@link Task}). - * @return The task implementing class. - */ - public String getTaskImplementingClass() { - return taskImplementingClass; - } + /** + * Returns the class that implements the actual task (must implement + * {@link Task}). + * + * @return The task implementing class. + */ + public String getTaskImplementingClass() { + return taskImplementingClass; + } - /** - * Sets the class that implements the actual task (must implement {@link Task}). - * @param taskImplementingClass The task implementing class. - */ - public void setTaskImplementingClass(String taskImplementingClass) { - this.taskImplementingClass = taskImplementingClass; - } + /** + * Sets the class that implements the actual task (must implement {@link Task}). + * + * @param taskImplementingClass The task implementing class. + */ + public void setTaskImplementingClass(final String taskImplementingClass) { + this.taskImplementingClass = taskImplementingClass; + } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - if (getId() != null) { - builder.append("id="); - builder.append(getId()); - } - if (async != DEFAULT_ASYNC) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("async="); - builder.append(async); - } - if (taskImplementingClass != null) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("taskImplementingClass="); - builder.append(taskImplementingClass); - } - if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("incomingTransitions="); - builder.append(getIncomingTransitions()); - } - if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("outgoingTransitions="); - builder.append(getOutgoingTransitions()); - } - builder.insert(0, "TaskInfo ["); - builder.append("]"); - return builder.toString(); - } + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + if (getId() != null) { + builder.append("id="); + builder.append(getId()); + } + if (async != DEFAULT_ASYNC) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("async="); + builder.append(async); + } + if (taskImplementingClass != null) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("taskImplementingClass="); + builder.append(taskImplementingClass); + } + if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("incomingTransitions="); + builder.append(getIncomingTransitions()); + } + if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("outgoingTransitions="); + builder.append(getOutgoingTransitions()); + } + builder.insert(0, "TaskInfo ["); + builder.append("]"); + return builder.toString(); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/Transition.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/Transition.java index 542ea7a8..39c5f437 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/Transition.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/model/Transition.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.model; import java.io.Serializable; @@ -31,132 +24,131 @@ import java.io.Serializable; import at.gv.egiz.eaaf.core.impl.idp.process.ProcessDefinitionParser; /** - * Represents a single transition from a {@link StartEvent} or {@linkplain TaskInfo Task} to another - * {@linkplain TaskInfo Task} or {@link EndEvent}. - * + * Represents a single transition from a {@link StartEvent} or + * {@linkplain TaskInfo Task} to another {@linkplain TaskInfo Task} or + * {@link EndEvent}. + * * @author tknall - * + * */ public class Transition implements Serializable { - private static final long serialVersionUID = 1L; - - private String id; - private String conditionExpression; - private ProcessNode from; - private ProcessNode to; - - /** - * Returns the process node (effectively a {@link StartEvent} or {@linkplain TaskInfo Task}) the transition is - * pointing from. - * - * @return The transition's source process node (never {@code null} if transition comes from a process definition - * from {@link ProcessDefinitionParser}). - */ - public ProcessNode getFrom() { - return from; - } - - /** - * Sets the process node the transition is pointing from. - * - * @param from - * The transition's source process node. - */ - public void setFrom(ProcessNode from) { - this.from = from; - } - - /** - * Returns the process node (effectively a {@linkplain TaskInfo Task} or {@link EndEvent}) the transition is - * pointing to. - * - * @return The transition's destination process node (never {@code null} if transition comes from a process - * definition from {@link ProcessDefinitionParser}). - */ - public ProcessNode getTo() { - return to; - } - - /** - * Sets the process node the transition is pointing to. - * - * @param to - * The transition's destination process node. - */ - public void setTo(ProcessNode to) { - this.to = to; - } - - /** - * Returns the unique identifier of the transition. - * - * @return The unique identifier (may be {@code null}). - */ - public String getId() { - return id; - } - - /** - * Sets the unique identifier of the transition. - * - * @param id - * The unique identifier. - */ - public void setId(String id) { - this.id = id; - } - - /** - * Returns the condition expression for this transition. - * - * @return The condition expression (may be {@code null}). - */ - public String getConditionExpression() { - return conditionExpression; - } - - /** - * Sets the condition expression for this transition. - * - * @param conditionExpression - * The condition expression. - */ - public void setConditionExpression(String conditionExpression) { - this.conditionExpression = conditionExpression; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - if (id != null) { - builder.append("id="); - builder.append(id); - } - if (from != null) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("from.id="); - builder.append(from.getId()); - } - if (to != null) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("to.id="); - builder.append(to.getId()); - } - if (conditionExpression != null) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append("conditionExpression="); - builder.append(conditionExpression); - } - builder.insert(0, "Transition ["); - builder.append("]"); - return builder.toString(); - } + private static final long serialVersionUID = 1L; + + private String id; + private String conditionExpression; + private ProcessNode from; + private ProcessNode to; + + /** + * Returns the process node (effectively a {@link StartEvent} or + * {@linkplain TaskInfo Task}) the transition is pointing from. + * + * @return The transition's source process node (never {@code null} if + * transition comes from a process definition from + * {@link ProcessDefinitionParser}). + */ + public ProcessNode getFrom() { + return from; + } + + /** + * Sets the process node the transition is pointing from. + * + * @param from The transition's source process node. + */ + public void setFrom(final ProcessNode from) { + this.from = from; + } + + /** + * Returns the process node (effectively a {@linkplain TaskInfo Task} or + * {@link EndEvent}) the transition is pointing to. + * + * @return The transition's destination process node (never {@code null} if + * transition comes from a process definition from + * {@link ProcessDefinitionParser}). + */ + public ProcessNode getTo() { + return to; + } + + /** + * Sets the process node the transition is pointing to. + * + * @param to The transition's destination process node. + */ + public void setTo(final ProcessNode to) { + this.to = to; + } + + /** + * Returns the unique identifier of the transition. + * + * @return The unique identifier (may be {@code null}). + */ + public String getId() { + return id; + } + + /** + * Sets the unique identifier of the transition. + * + * @param id The unique identifier. + */ + public void setId(final String id) { + this.id = id; + } + + /** + * Returns the condition expression for this transition. + * + * @return The condition expression (may be {@code null}). + */ + public String getConditionExpression() { + return conditionExpression; + } + + /** + * Sets the condition expression for this transition. + * + * @param conditionExpression The condition expression. + */ + public void setConditionExpression(final String conditionExpression) { + this.conditionExpression = conditionExpression; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + if (id != null) { + builder.append("id="); + builder.append(id); + } + if (from != null) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("from.id="); + builder.append(from.getId()); + } + if (to != null) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("to.id="); + builder.append(to.getId()); + } + if (conditionExpression != null) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append("conditionExpression="); + builder.append(conditionExpression); + } + builder.insert(0, "Transition ["); + builder.append("]"); + return builder.toString(); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/spring/SpringExpressionEvaluator.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/spring/SpringExpressionEvaluator.java index a91963e8..588a3bde 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/spring/SpringExpressionEvaluator.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/spring/SpringExpressionEvaluator.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.spring; import java.util.Objects; @@ -46,42 +39,43 @@ import at.gv.egiz.eaaf.core.api.idp.process.ExpressionEvaluator; import at.gv.egiz.eaaf.core.impl.idp.process.model.Transition; /** - * Expression evaluator for processing {@link Transition} conditions allowing to reference Spring beans from the - * application context. - * + * Expression evaluator for processing {@link Transition} conditions allowing to + * reference Spring beans from the application context. + * * @author tknall - * + * */ public class SpringExpressionEvaluator implements ExpressionEvaluator { - private Logger log = LoggerFactory.getLogger(getClass()); - private ExpressionParser parser = new SpelExpressionParser(); - private StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + private final Logger log = LoggerFactory.getLogger(getClass()); + private final ExpressionParser parser = new SpelExpressionParser(); + private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); - @Autowired(required = false) - private ApplicationContext ctx; + @Autowired(required = false) + private ApplicationContext ctx; - @PostConstruct - private void init() { - if (ctx != null) { - evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx)); - } - } + @PostConstruct + private void init() { + if (ctx != null) { + evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx)); + } + } - @Override - public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) { - Objects.requireNonNull(expression, "Expression must not be null."); - log.trace("Evaluating '{}'.", expression); + @Override + public boolean evaluate(final ExpressionEvaluationContext expressionContext, + final String expression) { + Objects.requireNonNull(expression, "Expression must not be null."); + log.trace("Evaluating '{}'.", expression); - Expression expr = parser.parseExpression(expression); - Boolean result = expr.getValue(evaluationContext, expressionContext, Boolean.class); - if (result == null) { - log.warn("Evaluation of '{}' results in null-value.", expression); - } else { - log.debug("Expression '{}' -> {}", expression, result); - } + final Expression expr = parser.parseExpression(expression); + final Boolean result = expr.getValue(evaluationContext, expressionContext, Boolean.class); + if (result == null) { + log.warn("Evaluation of '{}' results in null-value.", expression); + } else { + log.debug("Expression '{}' -> {}", expression, result); + } - return BooleanUtils.isTrue(result); - } + return BooleanUtils.isTrue(result); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/AbstractAuthSourceServlet.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/AbstractAuthSourceServlet.java index 4b007c4c..bd352bef 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/AbstractAuthSourceServlet.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/AbstractAuthSourceServlet.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.springweb; import javax.servlet.http.HttpServlet; @@ -41,102 +34,115 @@ import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine; import at.gv.egiz.eaaf.core.impl.idp.process.ProcessInstance; /** - * Abstract HttpServlet that provides means for retrieving the process engine (Spring Web required) as well as - * retrieving the underlying process instance and execution context evaluating a certain request parameter. - * + * Abstract HttpServlet that provides means for retrieving the process engine + * (Spring Web required) as well as retrieving the underlying process instance + * and execution context evaluating a certain request parameter. + * * @author tknall - * + * */ public abstract class AbstractAuthSourceServlet extends HttpServlet { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; + + private ProcessEngine processEngine; - private ProcessEngine processEngine; - - /** - * Returns the name of the request parameter representing the respective instance id. - * <p/>Default is {@code processInstanceId}. - * @return The request parameter name. - */ - public String getProcessInstanceIdParameterName() { - return "processInstanceId"; - } + /** + * Returns the name of the request parameter representing the respective + * instance id. + * <p/> + * Default is {@code processInstanceId}. + * + * @return The request parameter name. + */ + public String getProcessInstanceIdParameterName() { + return "processInstanceId"; + } - /** - * Returns the underlying process engine instance. - * - * @return The process engine (never {@code null}). - * @throws NoSuchBeanDefinitionException - * if no {@link ProcessEngine} bean was found. - * @throws NoUniqueBeanDefinitionException - * if more than one {@link ProcessEngine} bean was found. - * @throws BeansException - * if a problem getting the {@link ProcessEngine} bean occurred. - * @throws IllegalStateException - * if the Spring WebApplicationContext was not found, which means that the servlet is used outside a - * Spring web environment. - */ - public synchronized ProcessEngine getProcessEngine() { - if (processEngine == null) { - WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); - if (ctx == null) { - throw new IllegalStateException( - "Unable to find Spring WebApplicationContext. Servlet needs to be executed within a Spring web environment."); - } - processEngine = ctx.getBean(ProcessEngine.class); - } - return processEngine; - } + /** + * Returns the underlying process engine instance. + * + * @return The process engine (never {@code null}). + * @throws NoSuchBeanDefinitionException if no {@link ProcessEngine} bean was + * found. + * @throws NoUniqueBeanDefinitionException if more than one + * {@link ProcessEngine} bean was found. + * @throws BeansException if a problem getting the + * {@link ProcessEngine} bean occurred. + * @throws IllegalStateException if the Spring WebApplicationContext + * was not found, which means that the + * servlet is used outside a Spring web + * environment. + */ + public synchronized ProcessEngine getProcessEngine() { + if (processEngine == null) { + final WebApplicationContext ctx = + WebApplicationContextUtils.getWebApplicationContext(getServletContext()); + if (ctx == null) { + throw new IllegalStateException( + "Unable to find Spring WebApplicationContext. " + + "Servlet needs to be executed within a Spring web environment."); + } + processEngine = ctx.getBean(ProcessEngine.class); + } + return processEngine; + } - /** - * Retrieves the process instance referenced by the request parameter {@link #getProcessInstanceIdParameterName()}. - * - * @param request - * The HttpServletRequest. - * @return The process instance (never {@code null}). - * @throws NoSuchBeanDefinitionException - * if no {@link ProcessEngine} bean was found. - * @throws NoUniqueBeanDefinitionException - * if more than one {@link ProcessEngine} bean was found. - * @throws BeansException - * if a problem getting the {@link ProcessEngine} bean occurred. - * @throws IllegalStateException - * if the Spring WebApplicationContext was not found, which means that the servlet is used outside a - * Spring web environment. - * @throws IllegalArgumentException - * in case the process instance id referenced by the request parameter - * {@link #getProcessInstanceIdParameterName()} does not exist. - */ - public ProcessInstance getProcessInstance(HttpServletRequest request) { - String processInstanceId = StringUtils.trimToNull(request.getParameter(getProcessInstanceIdParameterName())); - if (processInstanceId == null) { - throw new IllegalArgumentException("Missing request parameter '" + getProcessInstanceIdParameterName() + "'."); - } - return getProcessEngine().getProcessInstance(processInstanceId); - } + /** + * Retrieves the process instance referenced by the request parameter + * {@link #getProcessInstanceIdParameterName()}. + * + * @param request The HttpServletRequest. + * @return The process instance (never {@code null}). + * @throws NoSuchBeanDefinitionException if no {@link ProcessEngine} bean was + * found. + * @throws NoUniqueBeanDefinitionException if more than one + * {@link ProcessEngine} bean was found. + * @throws BeansException if a problem getting the + * {@link ProcessEngine} bean occurred. + * @throws IllegalStateException if the Spring WebApplicationContext + * was not found, which means that the + * servlet is used outside a Spring web + * environment. + * @throws IllegalArgumentException in case the process instance id + * referenced by the request parameter + * {@link #getProcessInstanceIdParameterName()} + * does not exist. + */ + public ProcessInstance getProcessInstance(final HttpServletRequest request) { + final String processInstanceId = + StringUtils.trimToNull(request.getParameter(getProcessInstanceIdParameterName())); + if (processInstanceId == null) { + throw new IllegalArgumentException( + "Missing request parameter '" + getProcessInstanceIdParameterName() + "'."); + } + return getProcessEngine().getProcessInstance(processInstanceId); + } - /** - * Retrieves the execution context for the respective process instance referenced by the request parameter - * {@link #getProcessInstanceIdParameterName()}. - * - * @param request - * The HttpServletRequest. - * @return The execution context (never {@code null}). - * @throws NoSuchBeanDefinitionException - * if no {@link ProcessEngine} bean was found. - * @throws NoUniqueBeanDefinitionException - * if more than one {@link ProcessEngine} bean was found. - * @throws BeansException - * if a problem getting the {@link ProcessEngine} bean occurred. - * @throws IllegalStateException - * if the Spring WebApplicationContext was not found, which means that the servlet is used outside a - * Spring web environment. - * @throws IllegalArgumentException - * in case the process instance id referenced by the request parameter - * {@link #getProcessInstanceIdParameterName()} does not exist. - */ - public ExecutionContext getExecutionContext(HttpServletRequest request) { - return getProcessInstance(request).getExecutionContext(); - } + /** + * Retrieves the execution context for the respective process instance + * referenced by the request parameter + * {@link #getProcessInstanceIdParameterName()}. + * + * @param request The HttpServletRequest. + * @return The execution context (never {@code null}). + * @throws NoSuchBeanDefinitionException if no {@link ProcessEngine} bean was + * found. + * @throws NoUniqueBeanDefinitionException if more than one + * {@link ProcessEngine} bean was found. + * @throws BeansException if a problem getting the + * {@link ProcessEngine} bean occurred. + * @throws IllegalStateException if the Spring WebApplicationContext + * was not found, which means that the + * servlet is used outside a Spring web + * environment. + * @throws IllegalArgumentException in case the process instance id + * referenced by the request parameter + * {@link #getProcessInstanceIdParameterName()} + * does not exist. + */ + public ExecutionContext getExecutionContext(final HttpServletRequest request) { + return getProcessInstance(request).getExecutionContext(); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/AbstractTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/AbstractTask.java index b7a20d71..2cdb84c5 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/AbstractTask.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/AbstractTask.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.springweb; import javax.servlet.http.HttpServletRequest; @@ -40,11 +33,12 @@ import at.gv.egiz.eaaf.core.api.idp.process.Task; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; /** - * Abstract task implementation providing {@link HttpServletRequest} and {@link HttpServletResponse}. + * Abstract task implementation providing {@link HttpServletRequest} and + * {@link HttpServletResponse}. * <p/> - * Note that this abstract task requires the Spring (web) framework including a {@link RequestContextFilter} to be set - * within {@code web.xml}. - * + * Note that this abstract task requires the Spring (web) framework including a + * {@link RequestContextFilter} to be set within {@code web.xml}. + * * <pre> * ... * <filter> @@ -57,69 +51,74 @@ import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; * </filter-mapping> * ... * </pre> - * + * * @author tknall * @author tlenz - * + * */ public abstract class AbstractTask implements Task { - /** - * Executes the task providing the underlying {@link ExecutionContext} {@code executionContext} as well as the - * respective {@link HttpServletRequest} and {@link HttpServletResponse}. - * - * @param executionContext - * The execution context (never {@code null}). - * @param request - * The HttpServletRequest (never {@code null}). - * @param response - * The HttpServletResponse (never {@code null}). - * @throws IllegalStateException - * Thrown in case the task is nur being run within the required environment. Refer to javadoc for - * further information. - * @throws Exception - * Thrown in case of error executing the task. - */ - public abstract void execute(ExecutionContext executionContext, HttpServletRequest request, - HttpServletResponse response) throws TaskExecutionException; + @Override + public IRequest execute(final IRequest pendingReq, final ExecutionContext executionContext) + throws TaskExecutionException { + final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + if (requestAttributes != null && requestAttributes instanceof ServletRequestAttributes) { + final HttpServletRequest request = + ((ServletRequestAttributes) requestAttributes).getRequest(); + final HttpServletResponse response = + ((ServletRequestAttributes) requestAttributes).getResponse(); + if (request == null || response == null) { + throw new IllegalStateException( + "Spring's RequestContextHolder did not provide HttpServletResponse. " + + "Did you forget to set the required " + + "org.springframework.web.filter.RequestContextFilter in your web.xml."); + } + return internalExecute(pendingReq, executionContext, request, response); + } else { + throw new IllegalStateException("Task needs to be executed within a Spring web environment."); + } + } + + /** + * Executes the task providing the underlying {@link ExecutionContext} + * {@code executionContext} as well as the respective {@link HttpServletRequest} + * and {@link HttpServletResponse}. + * + * @param executionContext The execution context (never {@code null}). + * @param request The HttpServletRequest (never {@code null}). + * @param response The HttpServletResponse (never {@code null}). + * @throws IllegalStateException Thrown in case the task is nur being run within + * the required environment. Refer to javadoc for + * further information. + * @throws Exception Thrown in case of error executing the task. + */ + public abstract void execute(ExecutionContext executionContext, HttpServletRequest request, + HttpServletResponse response) throws TaskExecutionException; - /** - * Executes the task providing the underlying {@link ExecutionContext} {@code executionContext} - * and the {@link IRequest} {@code pendingReq }as well as the - * respective {@link HttpServletRequest} and {@link HttpServletResponse}. - * - * This method sets the pending-request object of the task implementation and starts the - * {@code execute} method of the task - * - * @param pendingReq The pending-request object (never {@code null}). - * @param executionContext The execution context (never {@code null}). - * @param request The HttpServletRequest (never {@code null}). - * @param response The HttpServletResponse (never {@code null}). - * @return The pending-request object, because Process-management works recursive - * - * @throws IllegalStateException - * Thrown in case the task is being run within the required environment. Refer to javadoc for - * further information. - * @throws Exception - * Thrown in case of error executing the task. - */ - protected abstract IRequest internalExecute(IRequest pendingReq, ExecutionContext executionContext, HttpServletRequest request, - HttpServletResponse response) throws TaskExecutionException; - - @Override - public IRequest execute(IRequest pendingReq, ExecutionContext executionContext) throws TaskExecutionException { - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - if (requestAttributes != null && requestAttributes instanceof ServletRequestAttributes) { - HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); - HttpServletResponse response = ((ServletRequestAttributes) requestAttributes).getResponse(); - if (request == null || response == null) { - throw new IllegalStateException( - "Spring's RequestContextHolder did not provide HttpServletResponse. Did you forget to set the required org.springframework.web.filter.RequestContextFilter in your web.xml."); - } - return internalExecute(pendingReq, executionContext, request, response); - } else { - throw new IllegalStateException("Task needs to be executed within a Spring web environment."); - } - } + /** + * Executes the task providing the underlying {@link ExecutionContext} + * {@code executionContext} and the {@link IRequest} {@code pendingReq }as well + * as the respective {@link HttpServletRequest} and {@link HttpServletResponse}. + * + * <p> + * This method sets the pending-request object of the task implementation and + * starts the {@code execute} method of the task + * </p> + * + * @param pendingReq The pending-request object (never {@code null}). + * @param executionContext The execution context (never {@code null}). + * @param request The HttpServletRequest (never {@code null}). + * @param response The HttpServletResponse (never {@code null}). + * @return The pending-request object, because Process-management works + * recursive + * + * @throws IllegalStateException Thrown in case the task is being run within the + * required environment. Refer to javadoc for + * further information. + * @throws Exception Thrown in case of error executing the task. + */ + protected abstract IRequest internalExecute(IRequest pendingReq, + ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException; } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/SpringWebExpressionEvaluator.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/SpringWebExpressionEvaluator.java index 5ebc1b58..afcc0a58 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/SpringWebExpressionEvaluator.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/springweb/SpringWebExpressionEvaluator.java @@ -1,43 +1,31 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.core.impl.idp.process.springweb; import java.io.Serializable; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.BooleanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,115 +43,92 @@ import at.gv.egiz.eaaf.core.api.idp.process.ExpressionEvaluator; import at.gv.egiz.eaaf.core.impl.idp.process.model.Transition; /** - * Expression evaluator for processing {@link Transition} conditions allowing to + * Expression evaluator for processing {@link Transition} conditions allowing + * to. * <ul> - * <li>reference Spring beans from the application context using {@code @myBeanName...},</li> + * <li>reference Spring beans from the application context using + * {@code @myBeanName...},</li> * <li>{@link ExecutionContext} properties using {@code ctx['property']},</li> - * <li>Multi valued {@link HttpServletRequest} parameters using {@code requestParameters['foo']} (keep in mind that this - * expression returns an array of String values) and</li> - * <li>Single valued {@link HttpServletRequest} parameters using {@code requestParameter['foo']}</li> + * <li>Multi valued {@link HttpServletRequest} parameters using + * {@code requestParameters['foo']} (keep in mind that this expression returns + * an array of String values) and</li> + * <li>Single valued {@link HttpServletRequest} parameters using + * {@code requestParameter['foo']}</li> * </ul> - * + * * @author tknall - * + * */ public class SpringWebExpressionEvaluator implements ExpressionEvaluator { - private Logger log = LoggerFactory.getLogger(getClass()); - private ExpressionParser parser = new SpelExpressionParser(); - private StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); - - @Autowired(required = false) - private ApplicationContext ctx; - - @Autowired(required = false) - private HttpServletRequest request; - - @PostConstruct - private void init() { - if (ctx != null) { - evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx)); - } - } - - /** - * Evaluation context that provides access to {@link HttpServletRequest} parameters using - * {@code requestParameter['foo']} for single value parameters or {@code requestParameters['foo']} for multi value - * parameters. Basic calls to {@code ctx} will be delegated. - * - * @author tknall - * - */ - private class SpringWebExpressionEvaluationContext implements ExpressionEvaluationContext { - - private static final long serialVersionUID = 1L; - - /** - * Creates a new expression evaluation context, providing access to HttpServletRequest parameter(s). - * - * @param delegate - * The original {@link ExpressionEvaluationContext} to be delegated to for {@code ctx['foo']} - * expressions. - */ - public SpringWebExpressionEvaluationContext(ExpressionEvaluationContext delegate) { - this.delegate = delegate; - } - - private ExpressionEvaluationContext delegate; - - @Override - public Map<String, Serializable> getCtx() { - return delegate.getCtx(); - } - - @SuppressWarnings("unused") - public Map<String, String> getRequestParameter() { - if (request != null) { - Map<String, String> singleValueMap = new HashMap<String, String>(); - Iterator<Entry<String, String[]>> it = request.getParameterMap().entrySet().iterator(); - while (it.hasNext()) { - Entry<String, String[]> entry = it.next(); - if (ArrayUtils.isNotEmpty(entry.getValue())) { - singleValueMap.put(entry.getKey(), entry.getValue()[0]); - } - } - return singleValueMap; - } else { - return Collections.<String, String> emptyMap(); - } - } - - @SuppressWarnings("unused") - public Map<String, String[]> getRequestParameters() { - if (request != null) { - return request.getParameterMap(); - } else { - return Collections.<String, String[]> emptyMap(); - } - } - - } - - @Override - public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) { - Objects.requireNonNull(expression, "Expression must not be null."); - log.trace("Evaluating '{}'.", expression); - - Expression expr = parser.parseExpression(expression); - Boolean result = null; - try { - result = expr.getValue(evaluationContext, new SpringWebExpressionEvaluationContext(expressionContext), - Boolean.class); - if (result == null) { - log.debug("Evaluation of '{}' results in null-value.", expression); - } else { - log.debug("Expression '{}' -> {}", expression, result); - } - } catch (Exception e) { - log.warn("Expression '{}' could not be processed.", expression, e); - } - - return BooleanUtils.isTrue(result); - } + private final Logger log = LoggerFactory.getLogger(getClass()); + private final ExpressionParser parser = new SpelExpressionParser(); + private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + + @Autowired(required = false) + private ApplicationContext ctx; + + @PostConstruct + private void init() { + if (ctx != null) { + evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx)); + } + } + + /** + * Evaluation context that provides access to {@link HttpServletRequest} + * parameters using {@code requestParameter['foo']} for single value parameters + * or {@code requestParameters['foo']} for multi value parameters. Basic calls + * to {@code ctx} will be delegated. + * + * @author tknall + * + */ + private static class SpringWebExpressionEvaluationContext implements ExpressionEvaluationContext { + + private static final long serialVersionUID = 1L; + + /** + * Creates a new expression evaluation context, providing access to + * HttpServletRequest parameter(s). + * + * @param delegate The original {@link ExpressionEvaluationContext} to be + * delegated to for {@code ctx['foo']} expressions. + */ + public SpringWebExpressionEvaluationContext(final ExpressionEvaluationContext delegate) { + this.delegate = delegate; + } + + private final ExpressionEvaluationContext delegate; + + @Override + public Map<String, Serializable> getCtx() { + return delegate.getCtx(); + } + + } + + @Override + public boolean evaluate(final ExpressionEvaluationContext expressionContext, + final String expression) { + Objects.requireNonNull(expression, "Expression must not be null."); + log.trace("Evaluating '{}'.", expression); + + final Expression expr = parser.parseExpression(expression); + Boolean result = null; + try { + result = expr.getValue(evaluationContext, + new SpringWebExpressionEvaluationContext(expressionContext), Boolean.class); + if (result == null) { + log.debug("Evaluation of '{}' results in null-value.", expression); + } else { + log.debug("Expression '{}' -> {}", expression, result); + } + } catch (final Exception e) { + log.warn("Expression '{}' could not be processed.", expression, e); + } + + return BooleanUtils.isTrue(result); + } } |