aboutsummaryrefslogtreecommitdiff
path: root/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment
diff options
context:
space:
mode:
authorThomas Lenz <tlenz@iaik.tugraz.at>2016-01-13 08:57:23 +0100
committerThomas Lenz <tlenz@iaik.tugraz.at>2016-01-13 08:57:23 +0100
commit22820de6b6fa074be1d9990766fa631a6f7f5818 (patch)
treedd5b795c1442a65061aafde34ca0f0eb8d6d741d /id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment
parent2683e6eee3b6f820fe5fa4ef1b76a94cdfcd846d (diff)
downloadmoa-id-spss-22820de6b6fa074be1d9990766fa631a6f7f5818.tar.gz
moa-id-spss-22820de6b6fa074be1d9990766fa631a6f7f5818.tar.bz2
moa-id-spss-22820de6b6fa074be1d9990766fa631a6f7f5818.zip
add test IDL generation
Diffstat (limited to 'id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment')
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java6
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java38
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java185
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java33
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java66
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java343
6 files changed, 664 insertions, 7 deletions
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java
index 8e38facbf..9f347b4ee 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java
@@ -55,4 +55,10 @@ public class Constants {
+ CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT + ".config.file";
public static final long CONFIG_PROPS_SKEWTIME = 2 * 60 * 1000; //2 minutes skew time for response validation
+
+ public static final String eIDAS_ATTR_PERSONALIDENTIFIER = "PersonIdentifier";
+ public static final String eIDAS_ATTR_DATEOFBIRTH = "DateOfBirth";
+ public static final String eIDAS_ATTR_CURRENTGIVENNAME = "CurrentGivenName";
+ public static final String eIDAS_ATTR_CURRENTFAMILYNAME = "CurrentFamilyName";
+
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java
new file mode 100644
index 000000000..7840ae2e6
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.egovernment.moa.id.auth.modules.eidas.exceptions;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttributeException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public eIDASAttributeException(String message) {
+ super(message);
+
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java
new file mode 100644
index 000000000..f4d6c4ad4
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java
@@ -0,0 +1,185 @@
+/*
+ * 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.egovernment.moa.id.auth.modules.eidas.tasks;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import eu.eidas.auth.commons.IPersonalAttributeList;
+
+import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
+import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger;
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.eIDASAttributeException;
+import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfiguration;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.moduls.RequestStorage;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.IdentityLinkReSigner;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * @author tlenz
+ *
+ */
+public class CreateIdentityLinkTask extends AbstractAuthServletTask {
+
+ /* (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{
+ String moasessionid = (String) executionContext.get(MOAIDAuthConstants.PARAM_SESSIONID);
+ String pendingRequestID = (String) executionContext.get("pendingRequestID");
+
+ //load pending request
+ IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID);
+ if (pendingReq == null) {
+ Logger.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure.");
+ throw new MOAIDException("auth.28", new Object[]{pendingRequestID});
+
+ }
+
+ //load MOASession object and OA-configuration
+ AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moasessionid);
+ IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration();
+
+ //get eIDAS attributes from MOA-Session
+ IPersonalAttributeList eIDASAttributes = moasession.getGenericDataFromSession(
+ AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST,
+ IPersonalAttributeList.class);
+
+ AuthConfiguration config = AuthConfigurationProviderFactory.getInstance();
+ IdentityLink identityLink = null;
+
+ //connect SZR-Gateway
+ //TODO: implement SZR-Gateway communication!!!!
+ if(true) {
+
+ // create fake IdL
+ // - fetch IdL template from resources
+ InputStream s = CreateIdentityLinkTask.class.getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml");
+ Element idlTemplate = DOMUtils.parseXmlValidating(s);
+
+ identityLink = new IdentityLinkAssertionParser(idlTemplate).parseIdentityLink();
+
+ // replace data
+ Element idlassertion = identityLink.getSamlAssertion();
+
+ // - set bpk/wpbk;
+ Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
+ if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_PERSONALIDENTIFIER))
+ throw new eIDASAttributeException("PersonalIdentifier is missing");
+ String eIdentifier = eIDASAttributes.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).getValue().get(0);
+ prIdentification.getFirstChild().setNodeValue(eIdentifier);
+
+ // - set last name
+ Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH);
+ if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_CURRENTFAMILYNAME))
+ throw new eIDASAttributeException("currentFamilyName is missing");
+ String familyName = eIDASAttributes.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME).getValue().get(0);
+ prFamilyName.getFirstChild().setNodeValue(familyName);
+
+ // - set first name
+ Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH);
+ if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_CURRENTGIVENNAME))
+ throw new eIDASAttributeException("currentGivenName is missing");
+ String givenName = eIDASAttributes.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME).getValue().get(0);
+ prGivenName.getFirstChild().setNodeValue(givenName);
+
+ // - set date of birth
+ Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH);
+ if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_DATEOFBIRTH))
+ throw new eIDASAttributeException("dateOfBirth is missing");
+ String dateOfBirth = eIDASAttributes.get(Constants.eIDAS_ATTR_DATEOFBIRTH).getValue().get(0);
+ dateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyyMMdd").parse(dateOfBirth));
+ prDateOfBirth.getFirstChild().setNodeValue(dateOfBirth);
+
+ identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink();
+
+ //resign IDL
+ IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance();
+ Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), config.getStorkFakeIdLResigningKey());
+ identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink();
+
+ } else {
+ //contact SZR Gateway
+ Logger.debug("Starting connecting SZR Gateway");
+
+ //TODO:!!!!!!
+
+ }
+
+ Logger.debug("SZR communication was successfull");
+
+ if (identityLink == null) {
+ Logger.error("SZR Gateway did not return an identity link.");
+ throw new MOAIDException("stork.10", null);
+ }
+
+ MOAReversionLogger.getInstance().logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_IDL_RECEIVED);
+ moasession.setForeigner(true);
+ moasession.setIdentityLink(identityLink);
+ moasession.setBkuURL("Not applicable (eIDASAuthentication)");
+
+ //store MOA-session to database
+ AuthenticationSessionStoreage.storeSession(moasession);
+
+ } catch (ParseException | MOAIDException | MOADatabaseException | ParserConfigurationException | SAXException | IOException e) {
+ throw new TaskExecutionException("IdentityLink generation for foreign person FAILED.", e);
+
+ } catch (eIDASAttributeException e) {
+ throw new TaskExecutionException("Minimum required eIDAS attributeset not found.", e);
+
+ }
+
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
index e80d62535..693807d63 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
@@ -10,13 +10,16 @@ import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList;
import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters;
import at.gv.egovernment.moa.id.moduls.IRequest;
import at.gv.egovernment.moa.id.moduls.RequestStorage;
@@ -68,20 +71,36 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask {
//TODO: check if additional decryption operation is required
}
+
+ //MOA-ID specific response validation
+ //TODO: implement MOA-ID specific response validation
+ //update MOA-Session data with received information
+ Logger.debug("Store eIDAS response information into MOA-session.");
+ moasession.setQAALevel(samlResp.getAssuranceLevel());
+ moasession.setCcc(samlResp.getCountry());
+
+ moasession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST,
+ new MOAPersonalAttributeList(samlResp.getPersonalAttributeList()));
+
+ moasession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.eIDAS_RESPONSE,
+ decSamlToken);
+
+ //set general information to MOA-Session
+ moasession.setAuthURL(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/");
-
-
- System.out.println(new String(decSamlToken));
-
+ //store MOA-session to database
+ AuthenticationSessionStoreage.storeSession(moasession);
}catch (EIDASSAMLEngineException e) {
Logger.error("eIDAS AuthnRequest generation FAILED.", e);
- throw new TaskExecutionException("eIDAS AuthnRequest generation FAILED.",
- new EIDASEngineException("Could not generate token for Saml Request", e));
+ throw new TaskExecutionException("eIDAS Response processing FAILED.",
+ new EIDASEngineException("Could not validate eIDAS response", e));
} catch (EIDASEngineException | MOAIDException | MOADatabaseException e) {
- throw new TaskExecutionException("eIDAS AuthnRequest generation FAILED.", e);
+ throw new TaskExecutionException("eIDAS Response processing FAILED.", e);
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java
new file mode 100644
index 000000000..573163af0
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java
@@ -0,0 +1,66 @@
+/*
+ * 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.egovernment.moa.id.auth.modules.eidas.utils;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import at.gv.egovernment.moa.logging.Logger;
+
+import eu.eidas.auth.commons.PersonalAttribute;
+import eu.eidas.auth.commons.PersonalAttributeList;
+
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAOrderedAttributeIterator implements Iterator<PersonalAttribute> {
+
+ private MOAPersonalAttributeList pal;
+ private Iterator<String> keyIterator;
+
+ public MOAOrderedAttributeIterator(MOAPersonalAttributeList palArg) {
+ this.pal = palArg;
+ keyIterator = palArg.getInsertOrder().iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return keyIterator.hasNext();
+ }
+
+ @Override
+ public PersonalAttribute next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ return pal.get(keyIterator.next());
+ }
+
+ @Override
+ public void remove() {
+ Logger.error("Not implemented");
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java
new file mode 100644
index 000000000..5cc100b70
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java
@@ -0,0 +1,343 @@
+/*
+ * 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.egovernment.moa.id.auth.modules.eidas.utils;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang.StringUtils;
+
+import at.gv.egovernment.moa.logging.Logger;
+
+import eu.eidas.auth.commons.AttributeConstants;
+import eu.eidas.auth.commons.AttributeUtil;
+import eu.eidas.auth.commons.EIDASErrors;
+import eu.eidas.auth.commons.EIDASParameters;
+import eu.eidas.auth.commons.EIDASUtil;
+import eu.eidas.auth.commons.EIDASValues;
+import eu.eidas.auth.commons.IPersonalAttributeList;
+import eu.eidas.auth.commons.PersonalAttribute;
+import eu.eidas.auth.commons.exceptions.InternalErrorEIDASException;
+
+/**
+ * @author tlenz
+ *
+ */
+public final class MOAPersonalAttributeList extends
+ ConcurrentHashMap<String, PersonalAttribute> implements IPersonalAttributeList {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4488124133022713089L;
+
+ public MOAPersonalAttributeList(IPersonalAttributeList eIDASAttributeList) {
+ super();
+ Iterator<PersonalAttribute> element = eIDASAttributeList.iterator();
+ while(element.hasNext())
+ add(element.next());
+
+ }
+
+ /**
+ * Hash with the latest fetched attribute name alias.
+ */
+ private Map<String, Integer> latestAttrAlias =
+ new HashMap<String, Integer>();
+
+ /**
+ * Hash with mapping number of alias or the attribute name.
+ */
+ private Map<String, Integer> attrAliasNumber =
+ new HashMap<String, Integer>();
+ private List<String> insertOrder = new ArrayList<String>();
+
+ /**
+ * Obtain the insertOrder Collection
+ *
+ * @return defensive copy of the collection
+ */
+ List<String> getInsertOrder() {
+ return Collections.unmodifiableList(this.insertOrder);
+ }
+
+ /**
+ * Default constructor.
+ */
+ public MOAPersonalAttributeList() {
+ super();
+
+ }
+
+ /**
+ * Constructor with initial capacity for the PersonalAttributeList size.
+ *
+ * @param capacity The initial capacity for the PersonalAttributeList.
+ */
+ public MOAPersonalAttributeList(final int capacity) {
+ super(capacity);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator<PersonalAttribute> iterator() {
+ return new MOAOrderedAttributeIterator(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PersonalAttribute get(final Object key) {
+ String attrName = (String) key;
+
+ if (this.latestAttrAlias == null)
+ this.latestAttrAlias = new HashMap<String, Integer>();
+
+ if (this.attrAliasNumber == null)
+ this.attrAliasNumber = new HashMap<String, Integer>();
+
+ if (this.latestAttrAlias.containsKey(key)) {
+ attrName = attrName + this.latestAttrAlias.get(key);
+ } else {
+ if (this.attrAliasNumber.containsKey(key)) {
+ this.latestAttrAlias.put(attrName, this.attrAliasNumber.get(key));
+ }
+ }
+ return super.get(attrName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void add(final PersonalAttribute value) {
+ if (value != null) {
+ this.put(value.getName(), value);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PersonalAttribute put(final String key, final PersonalAttribute val) {
+ if (StringUtils.isNotEmpty(key) && val != null) {
+ // Validate if attribute name already exists!
+ String attrAlias = key;
+ if (this.containsKey(attrAlias)) {
+ if (this.attrAliasNumber == null)
+ this.attrAliasNumber = new HashMap<String, Integer>();
+ if (!val.isEmptyValue() && StringUtils.isNumeric(val.getValue().get(0))) {
+ final String attrValue = val.getValue().get(0);
+ attrAlias = key + attrValue;
+ this.attrAliasNumber.put(key, Integer.valueOf(attrValue));
+ } else {
+ final PersonalAttribute attr = super.get(key);
+ if (!attr.isEmptyValue()
+ && StringUtils.isNumeric(attr.getValue().get(0))) {
+ attrAlias = key + attr.getValue().get(0);
+ super.put(key, (PersonalAttribute) attr);
+ this.attrAliasNumber.put(key, null);
+ }
+ }
+ } else {
+ if (insertOrder == null)
+ insertOrder = new ArrayList<String>();
+
+ insertOrder.add(key);
+ }
+ return super.put(attrAlias, val);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public PersonalAttribute remove(Object key) {
+ insertOrder.remove(key);
+ return super.remove(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void populate(final String attrList) {
+ final StringTokenizer strToken =
+ new StringTokenizer(attrList, EIDASValues.ATTRIBUTE_SEP.toString());
+
+ while (strToken.hasMoreTokens()) {
+ final PersonalAttribute persAttr = new PersonalAttribute();
+ String[] tuples =
+ strToken.nextToken().split(EIDASValues.ATTRIBUTE_TUPLE_SEP.toString(),
+ AttributeConstants.NUMBER_TUPLES.intValue());
+
+ // Convert to the new format if needed!
+ tuples = convertFormat(tuples);
+
+ if (AttributeUtil.hasValidTuples(tuples)) {
+ final int attrValueIndex =
+ AttributeConstants.ATTR_VALUE_INDEX.intValue();
+ final String tmpAttrValue =
+ tuples[attrValueIndex].substring(1,
+ tuples[attrValueIndex].length() - 1);
+ final String[] vals =
+ tmpAttrValue.split(EIDASValues.ATTRIBUTE_VALUE_SEP.toString());
+
+ persAttr.setName(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()]);
+ persAttr.setIsRequired(Boolean
+ .valueOf(tuples[AttributeConstants.ATTR_TYPE_INDEX.intValue()]));
+ // check if it is a complex value
+ if (tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()]
+ .equals(EIDASParameters.COMPLEX_ADDRESS_VALUE.toString())) {
+ persAttr.setComplexValue(createComplexValue(vals));
+ } else {
+ persAttr.setValue(createValues(vals));
+ }
+
+ if (tuples.length == AttributeConstants.NUMBER_TUPLES.intValue()) {
+ persAttr.setStatus(tuples[AttributeConstants.ATTR_STATUS_INDEX
+ .intValue()]);
+ }
+ this.put(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()],
+ persAttr);
+
+ } else {
+ Logger.info("BUSINESS EXCEPTION : Invalid personal attribute list tuples");
+ }
+
+ }
+ }
+
+ /**
+ * Returns a copy of this <tt>IPersonalAttributeList</tt> instance.
+ *
+ * @return The copy of this IPersonalAttributeList.
+ */
+ public Object clone() {
+ try {
+ MOAPersonalAttributeList theClone= (MOAPersonalAttributeList)super.clone();
+ theClone.insertOrder=new ArrayList<String>(insertOrder);
+ return theClone;
+
+ } catch (CloneNotSupportedException e) {
+ throw new InternalErrorEIDASException(
+ EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorCode()),
+ EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorMessage()), e);
+ }
+ }
+
+ /**
+ * Creates a string in the following format.
+ *
+ * attrName:attrType:[attrValue1,attrValue2=attrComplexValue]:attrStatus;
+ *
+ * @return {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ final StringBuilder strBuilder = new StringBuilder();
+ final Iterator<String> iteratorInsertOrder = insertOrder.iterator();
+ while (iteratorInsertOrder.hasNext()) {
+ String key = iteratorInsertOrder.next();
+ final PersonalAttribute attr = get(key);
+ strBuilder.append(attr.toString());
+ if (isNumberAlias(key)) {
+ strBuilder.append(get(key).toString());
+ }
+ }
+ return strBuilder.toString();
+ }
+
+ /**
+ * Validates and creates the attribute's complex values.
+ *
+ * @param values The complex values.
+ * @return The {@link Map} with the complex values.
+ * @see Map
+ */
+ private Map<String, String> createComplexValue(final String[] values) {
+ final Map<String, String> complexValue = new HashMap<String, String>();
+ for (final String val : values) {
+ final String[] tVal = val.split("=");
+ if (StringUtils.isNotEmpty(val) && tVal.length == 2) {
+ complexValue.put(tVal[0], AttributeUtil.unescape(tVal[1]));
+ }
+ }
+ return complexValue;
+ }
+
+ /**
+ * Validates and creates the attribute values.
+ *
+ * @param vals The attribute values.
+ * @return The {@link List} with the attribute values.
+ * @see List
+ */
+ private List<String> createValues(final String[] vals) {
+ final List<String> values = new ArrayList<String>();
+ for (final String val : vals) {
+ if (StringUtils.isNotEmpty(val)) {
+ values.add(AttributeUtil.unescape(val));
+ }
+ }
+ return values;
+ }
+
+ //////////////////
+ /**
+ * Converts the attribute tuple (attrName:attrType...) to the new format.
+ *
+ * @param tuples The attribute tuples to convert.
+ * @return The attribute tuples in the new format.
+ */
+ private String[] convertFormat(final String[] tuples) {
+ final String[] newFormatTuples =
+ new String[AttributeConstants.NUMBER_TUPLES.intValue()];
+ if (tuples != null) {
+ System.arraycopy(tuples, 0, newFormatTuples, 0, tuples.length);
+
+ for (int i = tuples.length; i < newFormatTuples.length; i++) {
+ if (i == AttributeConstants.ATTR_VALUE_INDEX.intValue()) {
+ newFormatTuples[i] = "[]";
+ } else {
+ newFormatTuples[i] = "";
+ }
+ }
+ }
+ return newFormatTuples;
+ }
+
+ public boolean isNumberAlias(String key) {
+ return this.attrAliasNumber.containsKey(key);
+ }
+
+
+
+}