diff options
Diffstat (limited to 'eaaf_core/src/main/java')
109 files changed, 11765 insertions, 11994 deletions
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/gui/IVelocityGuiFormBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/gui/IVelocityGuiFormBuilder.java index 103b38d9..e06140bf 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/gui/IVelocityGuiFormBuilder.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/gui/IVelocityGuiFormBuilder.java @@ -1,66 +1,67 @@ package at.gv.egiz.eaaf.core.api.gui; import java.io.InputStream; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; import org.apache.velocity.VelocityContext; -import at.gv.egiz.eaaf.core.exceptions.GUIBuildException; +public interface IVelocityGuiFormBuilder extends IGuiFormBuilder { + -public interface IVelocityGuiFormBuilder extends IGUIFormBuilder { + /** + * Generate a new {@link VelocityContext} and populate it with MOA-ID GUI parameters. + * + * @param config GUI builder configuration + * @return + */ + public VelocityContext generateVelocityContextFromConfiguration( + IVelocityGuiBuilderConfiguration config); - - /** - * Generate a new {@link VelocityContext} and populate it with MOA-ID GUI parameters - * - * @param config - * @return - */ - public VelocityContext generateVelocityContextFromConfiguration(IVelocityGUIBuilderConfiguration config); - - /** - * Load the template from different resources - * - * @param config - * @return An {@link InputStream} but never null. The {@link InputStream} had to be closed be the invoking method - * @throws GUIBuildException - */ - public InputStream getTemplateInputStream(IVelocityGUIBuilderConfiguration config) throws GUIBuildException; + /** + * Load the template from different resources. + * + * @param config GUI builder configuration + * @return An {@link InputStream} but never null. The {@link InputStream} had to be closed be the + * invoking method + * @throws GuiBuildException In case of an error + */ + public InputStream getTemplateInputStream(IVelocityGuiBuilderConfiguration config) + throws GuiBuildException; - /** - * Parse a GUI template, with parameters into a http servlet-response - * and use the default http-response content-type. - * <br><br> - * The parser use the <code>VelocityEngine</code> as internal template evaluator. - * - * @param httpReq http-request object - * @param httpResp http-response object - * @param config Configuration object - * @param loggerName String, which should be used from logger - * - * @throws GUIBuildException - */ - void build(HttpServletRequest httpReq, HttpServletResponse httpResp, IVelocityGUIBuilderConfiguration config, String loggerName) - throws GUIBuildException; + /** + * Parse a GUI template, with parameters into a http servlet-response and use the default + * http-response content-type. <br> + * <br> + * The parser use the <code>VelocityEngine</code> as internal template evaluator. + * + * @param httpReq http-request object + * @param httpResp http-response object + * @param config Configuration object + * @param loggerName String, which should be used from logger + * + * @throws GuiBuildException in case of an error + */ + void build(HttpServletRequest httpReq, HttpServletResponse httpResp, + IVelocityGuiBuilderConfiguration config, String loggerName) throws GuiBuildException; - /** - * Parse a GUI template, with parameters into a http servlet-response. - * <br><br> - * The parser use the <code>VelocityEngine</code> as internal template evaluator. - * - * @param httpReq http-request object - * @param httpResp http-response object - * @param config Configuration object - * @param contentType http-response content-type, which should be set - * @param loggerName String, which should be used from logger - * - * @throws GUIBuildException - */ - void build(HttpServletRequest httpReq, HttpServletResponse httpResp, IVelocityGUIBuilderConfiguration config, String contentType, - String loggerName) throws GUIBuildException; + /** + * Parse a GUI template, with parameters into a http servlet-response. <br> + * <br> + * The parser use the <code>VelocityEngine</code> as internal template evaluator. + * + * @param httpReq http-request object + * @param httpResp http-response object + * @param config Configuration object + * @param contentType http-response content-type, which should be set + * @param loggerName String, which should be used from logger + * + * @throws GuiBuildException In case of an error + */ + void build(HttpServletRequest httpReq, HttpServletResponse httpResp, + IVelocityGuiBuilderConfiguration config, String contentType, String loggerName) + throws GuiBuildException; } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExpressionEvaluationContext.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExpressionEvaluationContext.java index 31b8a219..7315dbf1 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExpressionEvaluationContext.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExpressionEvaluationContext.java @@ -1,48 +1,42 @@ -/******************************************************************************* - * 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.api.idp.process; import java.io.Serializable; import java.util.Map; +import at.gv.egiz.eaaf.core.impl.idp.process.model.Transition; /** * Context used for evaluation of condition expressions set for {@linkplain Transition Transitions}. - * + * * @author tknall - * + * */ public interface ExpressionEvaluationContext extends Serializable { - /** - * Returns the context data map used for expression evaluation. - * - * @return An unmodifiable map (never {@code null}). - */ - Map<String, Serializable> getCtx(); + /** + * Returns the context data map used for expression evaluation. + * + * @return An unmodifiable map (never {@code null}). + */ + Map<String, Serializable> getCtx(); } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExpressionEvaluator.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExpressionEvaluator.java index ef147bff..7fa67ae4 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExpressionEvaluator.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExpressionEvaluator.java @@ -1,51 +1,40 @@ -/******************************************************************************* - * 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.api.idp.process; /** * Evaluates a given {@code expression} returning a boolean value. - * + * * @author tknall */ public interface ExpressionEvaluator { - /** - * Evaluates a given {@code expression} returning a boolean value. - * - * @param expressionContext - * The context which can be used for evaluation of the expression. - * @param expression - * The expression resulting in a boolean (must not be {@code null}). - * @return A boolean value. - * @throws IllegalArgumentException - * In case of an invalid {@code expression}. - * @throws NullPointerException - * In case of a {@code null} expression. - */ - boolean evaluate(ExpressionEvaluationContext expressionContext, String expression); + /** + * Evaluates a given {@code expression} returning a boolean value. + * + * @param expressionContext The context which can be used for evaluation of the expression. + * @param expression The expression resulting in a boolean (must not be {@code null}). + * @return A boolean value. + * @throws IllegalArgumentException In case of an invalid {@code expression}. + * @throws NullPointerException In case of a {@code null} expression. + */ + boolean evaluate(ExpressionEvaluationContext expressionContext, String expression); } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessEngine.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessEngine.java index 6f6d6938..d4c221e0 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessEngine.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessEngine.java @@ -1,34 +1,26 @@ -/******************************************************************************* - * 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.api.idp.process; import java.io.InputStream; - import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; import at.gv.egiz.eaaf.core.impl.idp.process.ProcessDefinitionParserException; @@ -37,102 +29,98 @@ import at.gv.egiz.eaaf.core.impl.idp.process.model.ProcessDefinition; /** * Process engine providing means for starting and resuming processes. - * + * * @author tknall */ public interface ProcessEngine { - /** - * Registers a new process definition. Note that existing definitions with the same identifier will be replaced. - * - * @param processDefinition - * The process definition to be registered. - */ - void registerProcessDefinition(ProcessDefinition processDefinition); + /** + * Registers a new process definition. Note that existing definitions with the same identifier + * will be replaced. + * + * @param processDefinition The process definition to be registered. + */ + void registerProcessDefinition(ProcessDefinition processDefinition); + + /** + * Registers a new process definition given as {@link InputStream}. Note that existing definitions + * with the same identifier will be replaced. + * + * @param processDefinitionInputStream The input stream to the definition to be registered. + * @return The process definition's identifier. + * @throws ProcessDefinitionParserException Thrown in case of an error parsing the process + * definition. + */ + String registerProcessDefinition(InputStream processDefinitionInputStream) + throws ProcessDefinitionParserException; + + /** + * Creates a process instance according to the referenced process definition, persists it into the + * database and returns it identifier. + * <p/> + * Note that the method returns the identifier of a process instance which will be needed in order + * to start a process or to continue process execution after asynchronous task execution (refer to + * {@link #start(String)} and {@link #signal(String)} for further information). + * + * @param processDefinitionId The identifier of the respective process definition. + * @param executionContext The execution context (may be {@code null}). + * @return The id of the newly created process instance (never {@code null}). + * @throws ProcessExecutionException Thrown in case of error, e.g. when a + * {@code processDefinitionId} is referenced that does not exist. + */ + String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) + throws ProcessExecutionException; - /** - * Registers a new process definition given as {@link InputStream}. Note that existing definitions with the same identifier will be replaced. - * - * @param processDefinitionInputStream The input stream to the definition to be registered. - * @throws ProcessDefinitionParserException Thrown in case of an error parsing the process definition. - * @return The process definition's identifier. - */ - String registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException; + /** + * Creates a process instance according to the referenced process definition, persists it into the + * database and returns it identifier. + * <p/> + * Note that the method returns the identifier of a process instance which will be needed in order + * to start a process or to continue process execution after asynchronous task execution (refer to + * {@link #start(String)} and {@link #signal(String)} for further information). + * + * @param processDefinitionId The identifier of the respective process definition. + * @return The id of the newly created process instance (never {@code null}). + * @throws ProcessExecutionException Thrown in case of error, e.g. when a + * {@code processDefinitionId} is referenced that does not exist. + */ + String createProcessInstance(String processDefinitionId) throws ProcessExecutionException; - /** - * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier. - * <p/> - * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue - * process execution after asynchronous task execution (refer to {@link #start(String)} and - * {@link #signal(String)} for further information). - * - * @param processDefinitionId - * The identifier of the respective process definition. - * @param executionContext The execution context (may be {@code null}). - * @return The id of the newly created process instance (never {@code null}). - * @throws ProcessExecutionException - * Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist. - */ - String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException; - /** - * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier. - * <p/> - * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue - * process execution after asynchronous task execution (refer to {@link #start(String)} and - * {@link #signal(String)} for further information). - * - * @param processDefinitionId - * The identifier of the respective process definition. - * @return The id of the newly created process instance (never {@code null}). - * @throws ProcessExecutionException - * Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist. - */ - String createProcessInstance(String processDefinitionId) throws ProcessExecutionException; + /** + * Delete a process instance. + * + * @param processInstanceId The identifier of the respective process. + * @throws ProcessExecutionException Thrown in case of error, e.g. when a + * {@code processInstanceId} is referenced that does not exist. + */ + void deleteProcessInstance(String processInstanceId) throws ProcessExecutionException; - - /** - * Delete a process instance - * - * @param processInstanceId - * The identifier of the respective process. - * @throws ProcessExecutionException - * Thrown in case of error, e.g. when a {@code processInstanceId} is referenced that does not exist. - */ - void deleteProcessInstance(String processInstanceId) throws ProcessExecutionException; - - /** - * Returns the process instance with a given {@code processInstanceId}. - * - * @param processInstanceId - * The process instance id. - * @return The process instance (never {@code null}). - * @throws IllegalArgumentException - * In case the process instance does not/no longer exist. - * @throws RuntimeException - * In case the process instance could not be retrieved from persistence. - */ - ProcessInstance getProcessInstance(String processInstanceId); + /** + * Returns the process instance with a given {@code processInstanceId}. + * + * @param processInstanceId The process instance id. + * @return The process instance (never {@code null}). + * @throws IllegalArgumentException In case the process instance does not/no longer exist. + * @throws RuntimeException In case the process instance could not be retrieved from persistence. + */ + ProcessInstance getProcessInstance(String processInstanceId); - /** - * Starts the process using the given {@code pendingReq}. - * - * @param pendingReq - * The protocol request for which a process should be started. - * @throws ProcessExecutionException - * Thrown in case of error. - */ - void start(IRequest pendingReq) throws ProcessExecutionException; + /** + * Starts the process using the given {@code pendingReq}. + * + * @param pendingReq The protocol request for which a process should be started. + * @throws ProcessExecutionException Thrown in case of error. + */ + void start(IRequest pendingReq) throws ProcessExecutionException; - /** - * Resumes process execution after an asynchronous task has been executed. - * - * @param pendingReq - * The process instance id. - * @throws ProcessExecutionException - * Thrown in case of error. - */ - void signal(IRequest pendingReq) throws ProcessExecutionException; + /** + * Resumes process execution after an asynchronous task has been executed. + * + * @param pendingReq The process instance id. + * @throws ProcessExecutionException Thrown in case of error. + */ + void signal(IRequest pendingReq) throws ProcessExecutionException; -}
\ No newline at end of file +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessInstanceStoreDAO.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessInstanceStoreDAO.java deleted file mode 100644 index 305af911..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessInstanceStoreDAO.java +++ /dev/null @@ -1,71 +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.api.idp.process; - -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; -import at.gv.egiz.eaaf.core.impl.idp.process.ProcessInstance; -import at.gv.egiz.eaaf.core.impl.idp.process.dao.ProcessInstanceStore; - -public interface ProcessInstanceStoreDAO { - - /** - * Stores a {@link ProcessInstance} defined by {@code pIStore} in the - * database. - * - * @param pIStore - * the {@link ProcessInstanceStore} to persist. - * @throws EAAFStorageException - * is thrown if a problem occurs while accessing the database. - */ - void saveOrUpdate(ProcessInstanceStore pIStore) throws EAAFException; - - /** - * Returns a {@link ProcessInstanceStore}, defined by - * {@code processInstanceID} from the database, or {@code null} if the - * object could not be found. - * - * @param processInstanceId - * the id of the {@code ProcessInstanceStore} to retrieve. - * @return a ProcessInstanceStore, or {@code null}. - * @throws EAAFStorageException - * is thrown if a problem occurs while accessing the database. - */ - ProcessInstanceStore load(String processInstanceId) throws EAAFException; - - /** - * Deletes the {@link ProcessInstance} corresponding with the - * {@code processInstanceId}. - * - * @param processInstanceId - * the id of the {@code ProcessInstance} to be deleted. - * @throws EAAFStorageException - * is thrown if a problem occurs while accessing the database. - */ - void remove(String processInstanceId) throws EAAFException; - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessInstanceStoreDao.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessInstanceStoreDao.java new file mode 100644 index 00000000..641eeab8 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ProcessInstanceStoreDao.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.api.idp.process; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.impl.idp.process.ProcessInstance; +import at.gv.egiz.eaaf.core.impl.idp.process.dao.ProcessInstanceStore; + +public interface ProcessInstanceStoreDao { + + /** + * Stores a {@link ProcessInstance} defined by {@code pIStore} in the database. + * + * @param piStore the {@link ProcessInstanceStore} to persist. + * @throws EaafStorageException is thrown if a problem occurs while accessing the database. + */ + void saveOrUpdate(ProcessInstanceStore piStore) throws EaafException; + + /** + * Returns a {@link ProcessInstanceStore}, defined by {@code processInstanceID} from the database, + * or {@code null} if the object could not be found. + * + * @param processInstanceId the id of the {@code ProcessInstanceStore} to retrieve. + * @return a ProcessInstanceStore, or {@code null}. + * @throws EaafStorageException is thrown if a problem occurs while accessing the database. + */ + ProcessInstanceStore load(String processInstanceId) throws EaafException; + + /** + * Deletes the {@link ProcessInstance} corresponding with the {@code processInstanceId}. + * + * @param processInstanceId the id of the {@code ProcessInstance} to be deleted. + * @throws EaafStorageException is thrown if a problem occurs while accessing the database. + */ + void remove(String processInstanceId) throws EaafException; + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/Task.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/Task.java index 435dff12..06573403 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/Task.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/Task.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.api.idp.process; import at.gv.egiz.eaaf.core.api.IRequest; @@ -32,21 +25,21 @@ import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; /** * Represents a single task to be performed upon process execution. - * + * * @author tknall - * + * */ public interface Task { - /** - * Executes this task. - * @param pendingReq - * Provides the current processed protocol request - * @param executionContext - * Provides execution related information. - * @return The pending-request object, because Process-management works recursive - * @throws Exception An exception upon task execution. - */ - IRequest execute(IRequest pendingReq, ExecutionContext executionContext) throws TaskExecutionException; + /** + * Executes this task. + * + * @param pendingReq Provides the current processed protocol request + * @param executionContext Provides execution related information. + * @return The pending-request object, because Process-management works recursive + * @throws Exception An exception upon task execution. + */ + IRequest execute(IRequest pendingReq, ExecutionContext executionContext) + throws TaskExecutionException; } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/utils/IJsonMapper.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/utils/IJsonMapper.java index 6db5a6ae..dd7e69fd 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/utils/IJsonMapper.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/api/utils/IJsonMapper.java @@ -3,40 +3,45 @@ package at.gv.egiz.eaaf.core.api.utils; import java.io.IOException; import java.io.InputStream; -import at.gv.egiz.eaaf.core.exceptions.EAAFJsonMapperException; +import at.gv.egiz.eaaf.core.exceptions.EaafJsonMapperException; public interface IJsonMapper { - - /** - * Serialize an object to a JSON string. - * @param value the object to serialize - * @return a JSON string - * @throws JsonProcessingException thrown when an error occurs during serialization - */ - String serialize(Object value) throws EAAFJsonMapperException; - /** - * Deserialize a JSON string. - * - * @param value the JSON string to deserialize - * @param clazz optional parameter that determines the type of the returned object. If not set, an {@link Object} is returned. - * @return the deserialized JSON string as an object of type {@code clazz} or {@link Object} - * @throws JsonParseException if the JSON string contains invalid content. - * @throws JsonMappingException if the input JSON structure does not match structure expected for result type - * @throws IOException if an I/O problem occurs (e.g. unexpected end-of-input) - */ - <T> Object deserialize(String value, Class<T> clazz) throws EAAFJsonMapperException; + /** + * Serialize an object to a JSON string. + * + * @param value the object to serialize + * @return a JSON string + * @throws JsonProcessingException thrown when an error occurs during serialization + */ + String serialize(Object value) throws EaafJsonMapperException; - /** - * Deserialize a JSON string. - * - * @param is the JSON to deserialize as {@link InputStream} - * @param clazz optional parameter that determines the type of the returned object. If not set, an {@link Object} is returned. - * @return the deserialized JSON string as an object of type {@code clazz} or {@link Object} - * @throws JsonParseException if the JSON string contains invalid content. - * @throws JsonMappingException if the input JSON structure does not match structure expected for result type - * @throws IOException if an I/O problem occurs (e.g. unexpected end-of-input) - */ - <T> Object deserialize(InputStream is, Class<T> clazz) throws EAAFJsonMapperException; - -}
\ No newline at end of file + /** + * Deserialize a JSON string. + * + * @param value the JSON string to deserialize + * @param clazz optional parameter that determines the type of the returned object. If not set, an + * {@link Object} is returned. + * @return the deserialized JSON string as an object of type {@code clazz} or {@link Object} + * @throws JsonParseException if the JSON string contains invalid content. + * @throws JsonMappingException if the input JSON structure does not match structure expected for + * result type + * @throws IOException if an I/O problem occurs (e.g. unexpected end-of-input) + */ + <T> Object deserialize(String value, Class<T> clazz) throws EaafJsonMapperException; + + /** + * Deserialize a JSON string. + * + * @param is the JSON to deserialize as {@link InputStream} + * @param clazz optional parameter that determines the type of the returned object. If not set, an + * {@link Object} is returned. + * @return the deserialized JSON string as an object of type {@code clazz} or {@link Object} + * @throws JsonParseException if the JSON string contains invalid content. + * @throws JsonMappingException if the input JSON structure does not match structure expected for + * result type + * @throws IOException if an I/O problem occurs (e.g. unexpected end-of-input) + */ + <T> Object deserialize(InputStream is, Class<T> clazz) throws EaafJsonMapperException; + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/data/SLOInformationImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/data/SLOInformationImpl.java index 9f025979..c0980b0b 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/data/SLOInformationImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/data/SLOInformationImpl.java @@ -1,24 +1,20 @@ /******************************************************************************* - * 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. *******************************************************************************/ /******************************************************************************* *******************************************************************************/ @@ -27,165 +23,182 @@ package at.gv.egiz.eaaf.core.impl.data; import java.io.Serializable; - -import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; +import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface; /** * @author tlenz * */ -public class SLOInformationImpl implements SLOInformationInterface, Serializable { - - private static final long serialVersionUID = 295577931870512387L; - private String sessionIndex = null; - private String nameID = null; - private String protocolType = null; - private String nameIDFormat = null; - private String binding = null; - private String serviceURL = null; - private String authURL = null; - private String spEntityID = null; - - public SLOInformationImpl(String authURL, String spEntityID, String sessionID, String nameID, String nameIDFormat, String protocolType) { - new SLOInformationImpl(authURL, spEntityID, sessionID, nameID, nameIDFormat, protocolType, null, null); - } - - public SLOInformationImpl(String authURL, String spEntityID, String sessionID, String nameID, String nameIDFormat, String protocolType, String sloBinding, String sloLocationURL) { - this.sessionIndex = sessionID; - this.nameID = nameID; - this.nameIDFormat = nameIDFormat; - this.protocolType = protocolType; - this.spEntityID = spEntityID; - - if (authURL.endsWith("/")) - this.authURL = authURL.substring(0, authURL.length()-1); - else - this.authURL = authURL; - - - this.binding = sloBinding; - this.serviceURL = sloLocationURL; - - } - - - /** - * - */ - public SLOInformationImpl() { - - } - - - - /** - * @return the spEntityID - */ - public String getSpEntityID() { - return spEntityID; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.data.SLOInformationInterface#getSessionIndex() - */ - @Override - public String getSessionIndex() { - return sessionIndex; - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.data.SLOInformationInterface#getUserNameIdentifier() - */ - @Override - public String getUserNameIdentifier() { - return nameID; - - } - - - /** - * @param sessionIndex the sessionIndex to set - */ - public void setSessionIndex(String sessionIndex) { - this.sessionIndex = sessionIndex; - } - - - /** - * @param nameID the nameID to set - */ - public void setUserNameIdentifier(String nameID) { - this.nameID = nameID; - } - - - - /** - * @param protocolType the protocolType to set - */ - public void setProtocolType(String protocolType) { - this.protocolType = protocolType; - } - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.data.SLOInformationInterface#getProtocolType() - */ - @Override - public String getProtocolType() { - return protocolType; - } - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.data.SLOInformationInterface#getUserNameIDFormat() - */ - @Override - public String getUserNameIDFormat() { - return this.nameIDFormat; - } - - - /** - * @param nameIDFormat the nameIDFormat to set - */ - public void setNameIDFormat(String nameIDFormat) { - this.nameIDFormat = nameIDFormat; - } - - /** - * @return the binding - */ - public String getBinding() { - return binding; - } - - /** - * @return the serviceURL - */ - public String getServiceURL() { - return serviceURL; - } - - /** - * @return the authURL from requested IDP without ending / - */ - public String getAuthURL() { - return authURL; - } - - /** - * @param spEntityID the spEntityID to set - */ - public void setSpEntityID(String spEntityID) { - this.spEntityID = spEntityID; - } - - - - - +public class SLOInformationImpl implements SloInformationInterface, Serializable { + + private static final long serialVersionUID = 295577931870512387L; + private String sessionIndex = null; + private String nameID = null; + private String protocolType = null; + private String nameIDFormat = null; + private String binding = null; + private String serviceURL = null; + private String authURL = null; + private String spEntityID = null; + + public SLOInformationImpl(final String authURL, final String spEntityID, final String sessionID, + final String nameID, final String nameIDFormat, final String protocolType) { + this(authURL, spEntityID, sessionID, nameID, nameIDFormat, protocolType, null, + null); + + } + + public SLOInformationImpl(final String authURL, final String spEntityID, final String sessionID, + final String nameID, final String nameIDFormat, final String protocolType, + final String sloBinding, final String sloLocationURL) { + this.sessionIndex = sessionID; + this.nameID = nameID; + this.nameIDFormat = nameIDFormat; + this.protocolType = protocolType; + this.spEntityID = spEntityID; + + if (authURL.endsWith("/")) { + this.authURL = authURL.substring(0, authURL.length() - 1); + } else { + this.authURL = authURL; + } + + + this.binding = sloBinding; + this.serviceURL = sloLocationURL; + + } + + + /** + * + */ + public SLOInformationImpl() { + + } + + + + /** + * @return the spEntityID + */ + @Override + public String getSpEntityID() { + return spEntityID; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.data.SLOInformationInterface#getSessionIndex() + */ + @Override + public String getSessionIndex() { + return sessionIndex; + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.data.SLOInformationInterface#getUserNameIdentifier() + */ + @Override + public String getUserNameIdentifier() { + return nameID; + + } + + + /** + * @param sessionIndex the sessionIndex to set + */ + @Override + public void setSessionIndex(final String sessionIndex) { + this.sessionIndex = sessionIndex; + } + + + /** + * @param nameID the nameID to set + */ + @Override + public void setUserNameIdentifier(final String nameID) { + this.nameID = nameID; + } + + + + /** + * @param protocolType the protocolType to set + */ + public void setProtocolType(final String protocolType) { + this.protocolType = protocolType; + } + + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.data.SLOInformationInterface#getProtocolType() + */ + @Override + public String getProtocolType() { + return protocolType; + } + + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.data.SLOInformationInterface#getUserNameIDFormat() + */ + @Override + public String getUserNameIdFormat() { + return this.nameIDFormat; + } + + + /** + * @param nameIDFormat the nameIDFormat to set + */ + @Override + public void setNameIdFormat(final String nameIDFormat) { + this.nameIDFormat = nameIDFormat; + } + + /** + * @return the binding + */ + @Override + public String getBinding() { + return binding; + } + + /** + * @return the serviceURL + */ + @Override + public String getServiceUrl() { + return serviceURL; + } + + /** + * @return the authURL from requested IDP without ending / + */ + @Override + public String getAuthUrl() { + return authURL; + } + + /** + * @param spEntityID the spEntityID to set + */ + public void setSpEntityID(final String spEntityID) { + this.spEntityID = spEntityID; + } + + } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGUIFormBuilderConfiguration.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGUIFormBuilderConfiguration.java deleted file mode 100644 index dde5ab70..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGUIFormBuilderConfiguration.java +++ /dev/null @@ -1,179 +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.gui; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.api.gui.GroupDefinition; -import at.gv.egiz.eaaf.core.api.gui.GroupDefinition.TYPE; -import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfiguration; - -/** - * @author tlenz - * - */ -public abstract class AbstractGUIFormBuilderConfiguration implements IGUIBuilderConfiguration { - private static final Logger log = LoggerFactory.getLogger(AbstractGUIFormBuilderConfiguration.class); - - public static final GroupDefinition PARAM_GROUP_FORM = GroupDefinition.getInstance("form", TYPE.MAP); - public static final GroupDefinition PARAM_GROUP_ACTIONS = GroupDefinition.getInstance("actions", TYPE.LIST); - public static final GroupDefinition PARAM_GROUP_PARAMS = GroupDefinition.getInstance("params", TYPE.MAP); - public static final GroupDefinition PARAM_GROUP_UIOPTIONS = GroupDefinition.getInstance("uiOptions", TYPE.MAP); - public static final GroupDefinition PARAM_GROUP_MSG = GroupDefinition.getInstance("msg", TYPE.MAP); - - - public static final String PARAM_VIEWNAME = "viewName"; - public static final String PARAM_AUTHCONTEXT = "contextPath"; - public static final String PARAM_FORMSUBMITENDPOINT = "submitEndpoint"; - @Deprecated public static final String PARAM_PENDINGREQUESTID_DEPRECATED = "pendingReqID"; - public static final String PARAM_PENDINGREQUESTID = "pendingid"; - - private String authURL = null; - private String viewName = null; - private String formSubmitEndpoint = null; - - private final Map<String, Object> params = new HashMap<String, Object>(); - - /** - * @param authURL IDP PublicURL-Prefix which should be used, but never null - * @param viewName Name of the template (with suffix) but never null - * @param formSubmitEndpoint EndPoint on which the form should be submitted, - * or null if the form must not submitted - * - */ - public AbstractGUIFormBuilderConfiguration(String authURL, String viewName, String formSubmitEndpoint) { - if (viewName.startsWith("/")) - this.viewName = viewName.substring(1); - else - this.viewName = viewName; - - if (authURL.endsWith("/")) - this.authURL = authURL.substring(0, authURL.length() - 1); - else - this.authURL = authURL; - - if (StringUtils.isNotEmpty(formSubmitEndpoint)) { - if (formSubmitEndpoint.startsWith("/")) - this.formSubmitEndpoint = formSubmitEndpoint; - else - this.formSubmitEndpoint = "/" + formSubmitEndpoint; - } - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.frontend.builder.IGUIBuilderConfiguration#getViewName() - */ - @Override - public final String getViewName() { - return this.viewName; - - } - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.frontend.builder.IGUIBuilderConfiguration#getViewParameters() - */ - @Override - public final Map<String, Object> getViewParameters() { - //set generic parameters - setViewParameter(getFromGroup(), PARAM_AUTHCONTEXT, this.authURL); - setViewParameter(getFromGroup(), PARAM_FORMSUBMITENDPOINT, this.formSubmitEndpoint); - setViewParameter(getFromGroup(), PARAM_VIEWNAME, this.viewName); - - //get parameters from detail implementation - putSpecificViewParameters(); - - try { - log.trace("Full view parameters: {}", StringUtils.join(params, ",")); - } catch (final Exception e) { - log.info("Can NOT trace view parameters. Reason: {}", e.getMessage() ); - } - - return params; - - } - - /** - * Define the parameters, which should be evaluated in the template <br> - * <b>IMPORTANT:</b> external HTML escapetion is required, because it is NOT done internally during the building process - * - */ - abstract protected void putSpecificViewParameters(); - - /** - * Get the Group for generic form elements - * - * @return {@link GroupDefinition} or <code>null</code> if no groups are used - */ - abstract protected GroupDefinition getFromGroup(); - - @SuppressWarnings("unchecked") - protected void setViewParameter(GroupDefinition groupDefinition, String key, Object value) { - - if (groupDefinition != null) { - log.trace("Adding group object ... "); - Object groupMap = params.get(groupDefinition.getName()); - if (groupMap == null) { - if (groupDefinition.getType().equals(TYPE.MAP)) { - groupMap = new HashMap<String, Object>();; - log.trace("Build new MAP based group element"); - - } else if (groupDefinition.getType().equals(TYPE.LIST)) { - groupMap = new ArrayList<Object>(); - log.trace("Build new List based group element"); - - } else - log.warn("GroupDefinition contains an unknown type: {}", groupDefinition.getType().name()); - - } - - params.put(groupDefinition.getName(), groupMap); - if (groupMap instanceof Map<?,?>) - ((Map<String, Object>) groupMap).put(key, value); - - else if (groupMap instanceof List<?>) - ((List<Object>)groupMap).add(value); - - else - log.warn("Can NOT add element: {} to group: {}, because group is of type: {}", - key, groupDefinition.getName(), groupMap.getClass().getName()); - - } else { - log.trace("Add root object ... "); - params.put(key, value); - - } - - } -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGuiFormBuilderConfiguration.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGuiFormBuilderConfiguration.java new file mode 100644 index 00000000..efb8c713 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractGuiFormBuilderConfiguration.java @@ -0,0 +1,195 @@ +/* + * 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.gui; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import at.gv.egiz.eaaf.core.api.gui.GroupDefinition; +import at.gv.egiz.eaaf.core.api.gui.GroupDefinition.Type; +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract Configuration implementation for GUI Builders. + * + * @author tlenz + * + */ +public abstract class AbstractGuiFormBuilderConfiguration implements IGuiBuilderConfiguration { + private static final Logger log = + LoggerFactory.getLogger(AbstractGuiFormBuilderConfiguration.class); + + public static final GroupDefinition PARAM_GROUP_FORM = + GroupDefinition.getInstance("form", Type.MAP); + public static final GroupDefinition PARAM_GROUP_ACTIONS = + GroupDefinition.getInstance("actions", Type.LIST); + public static final GroupDefinition PARAM_GROUP_PARAMS = + GroupDefinition.getInstance("params", Type.MAP); + public static final GroupDefinition PARAM_GROUP_UIOPTIONS = + GroupDefinition.getInstance("uiOptions", Type.MAP); + public static final GroupDefinition PARAM_GROUP_MSG = + GroupDefinition.getInstance("msg", Type.MAP); + + + public static final String PARAM_VIEWNAME = "viewName"; + public static final String PARAM_AUTHCONTEXT = "contextPath"; + public static final String PARAM_FORMSUBMITENDPOINT = "submitEndpoint"; + @Deprecated + public static final String PARAM_PENDINGREQUESTID_DEPRECATED = "pendingReqID"; + public static final String PARAM_PENDINGREQUESTID = "pendingid"; + + private String authUrl = null; + private String viewName = null; + private String formSubmitEndpoint = null; + + private final Map<String, Object> params = new HashMap<>(); + + /** + * Abstract GUI Builder config. + * + * @param authUrl IDP PublicURL-Prefix which should be used, but never null + * @param viewName Name of the template (with suffix) but never null + * @param formSubmitEndpoint EndPoint on which the form should be submitted, or null if the form + * must not submitted + * + */ + public AbstractGuiFormBuilderConfiguration(final String authUrl, final String viewName, + final String formSubmitEndpoint) { + if (viewName.startsWith("/")) { + this.viewName = viewName.substring(1); + } else { + this.viewName = viewName; + } + + if (authUrl.endsWith("/")) { + this.authUrl = authUrl.substring(0, authUrl.length() - 1); + } else { + this.authUrl = authUrl; + } + + if (StringUtils.isNotEmpty(formSubmitEndpoint)) { + if (formSubmitEndpoint.startsWith("/")) { + this.formSubmitEndpoint = formSubmitEndpoint; + } else { + this.formSubmitEndpoint = "/" + formSubmitEndpoint; + } + } + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.frontend.builder.IGUIBuilderConfiguration#getViewName() + */ + @Override + public final String getViewName() { + return this.viewName; + + } + + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.auth.frontend.builder.IGUIBuilderConfiguration#getViewParameters() + */ + @Override + public final Map<String, Object> getViewParameters() { + // set generic parameters + setViewParameter(getFromGroup(), PARAM_AUTHCONTEXT, this.authUrl); + setViewParameter(getFromGroup(), PARAM_FORMSUBMITENDPOINT, this.formSubmitEndpoint); + setViewParameter(getFromGroup(), PARAM_VIEWNAME, this.viewName); + + // get parameters from detail implementation + putSpecificViewParameters(); + + try { + log.trace("Full view parameters: {}", StringUtils.join(params, ",")); + } catch (final Exception e) { + log.info("Can NOT trace view parameters. Reason: {}", e.getMessage()); + } + + return params; + + } + + /** + * Define the parameters, which should be evaluated in the template. <br> + * <b>IMPORTANT:</b> external HTML escapetion is required, because it is NOT done internally + * during the building process + * + */ + protected abstract void putSpecificViewParameters(); + + /** + * Get the Group for generic form elements. + * + * @return {@link GroupDefinition} or <code>null</code> if no groups are used + */ + protected abstract GroupDefinition getFromGroup(); + + @SuppressWarnings("unchecked") + protected void setViewParameter(final GroupDefinition groupDefinition, final String key, + final Object value) { + + if (groupDefinition != null) { + log.trace("Adding group object ... "); + Object groupMap = params.get(groupDefinition.getName()); + if (groupMap == null) { + if (groupDefinition.getType().equals(Type.MAP)) { + groupMap = new HashMap<String, Object>(); + log.trace("Build new MAP based group element"); + + } else if (groupDefinition.getType().equals(Type.LIST)) { + groupMap = new ArrayList<>(); + log.trace("Build new List based group element"); + + } else { + log.warn("GroupDefinition contains an unknown type: {}", + groupDefinition.getType().name()); + groupMap = StringUtils.EMPTY; + + } + + } + + params.put(groupDefinition.getName(), groupMap); + if (groupMap instanceof Map<?, ?>) { + ((Map<String, Object>) groupMap).put(key, value); + } else if (groupMap instanceof List<?>) { + ((List<Object>) groupMap).add(value); + } else { + log.warn("Can NOT add element: {} to group: {}, because group is of type: {}", key, + groupDefinition.getName(), groupMap.getClass().getName()); + } + + } else { + log.trace("Add root object ... "); + params.put(key, value); + + } + + } +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractVelocityGUIFormBuilderImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractVelocityGUIFormBuilderImpl.java deleted file mode 100644 index b9c16538..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractVelocityGUIFormBuilderImpl.java +++ /dev/null @@ -1,242 +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.gui; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringWriter; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.VelocityEngine; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -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.IVelocityGUIBuilderConfiguration; -import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder; -import at.gv.egiz.eaaf.core.exceptions.GUIBuildException; -import at.gv.egiz.eaaf.core.impl.gui.velocity.VelocityProvider; - -/** - * @author tlenz - * - */ -public abstract class AbstractVelocityGUIFormBuilderImpl implements IVelocityGuiFormBuilder { - private static final Logger log = LoggerFactory.getLogger(AbstractVelocityGUIFormBuilderImpl.class); - private static final String DEFAULT_CONTENT_TYPE = EAAFConstants.CONTENTTYPE_HTML_UTF8; - - private VelocityEngine engine; - - public AbstractVelocityGUIFormBuilderImpl() throws GUIBuildException { - try { - engine = VelocityProvider.getClassPathVelocityEngine(); - - } catch (final Exception e) { - log.error("Initialization of Velocity-Engine to render GUI components FAILED.", e); - throw new GUIBuildException("Initialization of Velocity-Engine to render GUI components FAILED.", e); - - } - - } - - @Override - public final void build(HttpServletRequest httpReq, HttpServletResponse httpResp, IGUIBuilderConfiguration config, - String loggerName) throws GUIBuildException { - if (config instanceof IVelocityGUIBuilderConfiguration) - build(httpReq, httpResp, (IVelocityGUIBuilderConfiguration)config, loggerName); - else - throw new IllegalStateException(this.getClass().getName() + " needs a " + IVelocityGUIBuilderConfiguration.class.getName()); - - - } - - @Override - public final void build(HttpServletRequest httpReq, HttpServletResponse httpResp, IGUIBuilderConfiguration config, - String contentType, String loggerName) throws GUIBuildException { - if (config instanceof IVelocityGUIBuilderConfiguration) - build(httpReq, httpResp, (IVelocityGUIBuilderConfiguration)config, contentType, loggerName); - else - throw new IllegalStateException(this.getClass().getName() + " needs a " + IVelocityGUIBuilderConfiguration.class.getName()); - - } - - @Override - public void build(HttpServletRequest httpReq, HttpServletResponse httpResp, IVelocityGUIBuilderConfiguration config, String loggerName) throws GUIBuildException { - build(httpReq, httpResp, config, getInternalContentType(config), loggerName); - - } - - @Override - public void build(HttpServletRequest httpReq, HttpServletResponse httpResp, IVelocityGUIBuilderConfiguration config, - String contentType, String loggerName) throws GUIBuildException { - - InputStream is = null; - try { - final String viewName = config.getViewName(); - is = getTemplateInputStream(config); - - //build Velocity Context from input paramters - final VelocityContext context = buildContextFromViewParams(config.getViewParameters()); - - //evaluate template - final StringWriter writer = new StringWriter(); - engine.evaluate(context, writer, loggerName, new BufferedReader(new InputStreamReader(is))); - - //write template to response - final byte[] content = writer.toString().getBytes("UTF-8"); - httpResp.setStatus(HttpServletResponse.SC_OK); - httpResp.setContentLength(content.length); - httpResp.setContentType(contentType); - httpResp.getOutputStream().write(content); - - if (log.isTraceEnabled()) { - log.trace("Write Content for viewName:" + viewName - + ". Contentsize:" + String.valueOf(content.length) - + " BufferSize:" + httpResp.getBufferSize() - + " ContentType:" + contentType); - for (final String el : httpResp.getHeaderNames()) - log.trace(" * Headername:" + el + " Value:" + httpResp.getHeader(el)); - - } - - } catch (final IOException e) { - log.error("GUI form-builder has an internal error.", e); - throw new GUIBuildException("GUI form-builder has an internal error.", e); - - } finally { - if (is != null) - try { - is.close(); - - } catch (final IOException e) { - log.error("Can NOT close GUI-Template InputStream.", e); - - } - } - - } - - /** - * Generate a new {@link VelocityContext} and populate it with MOA-ID GUI parameters - * - * @param config - * @return - */ - @Override - public VelocityContext generateVelocityContextFromConfiguration(IVelocityGUIBuilderConfiguration config) { - return buildContextFromViewParams(config.getViewParameters()); - - } - - /** - * Load the template from different resources - * - * @param config - * @return An {@link InputStream} but never null. The {@link InputStream} had to be closed be the invoking method - * @throws GUIBuildException - */ - @Override - public InputStream getTemplateInputStream(IVelocityGUIBuilderConfiguration config) throws GUIBuildException { - InputStream is = config.getTemplate(config.getViewName()); - if (is == null) { - log.trace("Loading GUI template:" + config.getViewName() + " from default resources ... "); - is = getInternalTemplate(config); - - if (is == null) { - log.warn("No GUI with viewName:" + config.getViewName() + " FOUND."); - throw new GUIBuildException("No GUI with viewName:" + config.getViewName() + " FOUND."); - - } - } - return is; - - } - - /** - * Load an internal template from default resources - * - * @param config - * @return - * @throws GUIBuildException - */ - abstract protected InputStream getInternalTemplate(IVelocityGUIBuilderConfiguration config) throws GUIBuildException; - - - /** - * @return - */ - protected String getInternalClasspathTemplateDir(IVelocityGUIBuilderConfiguration config, String defaultClassPathDir) { - String dir = config.getClasspathTemplateDir(); - if (dir != null) { - if (!dir.endsWith("/")) - dir += "/"; - - return dir; - - } else - return defaultClassPathDir; - } - - /** - * @param viewParams - * @return - */ - private VelocityContext buildContextFromViewParams(Map<String, Object> viewParams) { - final VelocityContext context = new VelocityContext(); - - if (viewParams != null) { - final Iterator<Entry<String, Object>> interator = viewParams.entrySet().iterator(); - while (interator.hasNext()) { - final Entry<String, Object> el = interator.next(); - context.put(el.getKey(), el.getValue()); - } - - } - - return context; - } - - private String getInternalContentType(IGUIBuilderConfiguration config) { - if (StringUtils.isEmpty(config.getDefaultContentType())) - return DEFAULT_CONTENT_TYPE; - - else - return config.getDefaultContentType(); - - } - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractVelocityGuiFormBuilderImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractVelocityGuiFormBuilderImpl.java new file mode 100644 index 00000000..0ab5fa49 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/AbstractVelocityGuiFormBuilderImpl.java @@ -0,0 +1,250 @@ +/* + * 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.gui; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +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.IVelocityGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.impl.gui.velocity.VelocityProvider; +import org.apache.commons.lang3.StringUtils; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract VeloCity based GUI builder implementation. + * + * @author tlenz + * + */ +public abstract class AbstractVelocityGuiFormBuilderImpl implements IVelocityGuiFormBuilder { + private static final Logger log = + LoggerFactory.getLogger(AbstractVelocityGuiFormBuilderImpl.class); + private static final String DEFAULT_CONTENT_TYPE = EAAFConstants.CONTENTTYPE_HTML_UTF8; + + private VelocityEngine engine; + + /** + * Velocity based GUI builder. + * + * @throws GuiBuildException In case of a error + */ + public AbstractVelocityGuiFormBuilderImpl() throws GuiBuildException { + try { + engine = VelocityProvider.getClassPathVelocityEngine(); + + } catch (final Exception e) { + log.error("Initialization of Velocity-Engine to render GUI components FAILED.", e); + throw new GuiBuildException( + "Initialization of Velocity-Engine to render GUI components FAILED.", e); + + } + + } + + @Override + public final void build(final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final IGuiBuilderConfiguration config, final String loggerName) throws GuiBuildException { + if (config instanceof IVelocityGuiBuilderConfiguration) { + build(httpReq, httpResp, (IVelocityGuiBuilderConfiguration) config, loggerName); + } else { + throw new IllegalStateException(this.getClass().getName() + " needs a " + + IVelocityGuiBuilderConfiguration.class.getName()); + } + + + } + + @Override + public final void build(final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final IGuiBuilderConfiguration config, final String contentType, final String loggerName) + throws GuiBuildException { + if (config instanceof IVelocityGuiBuilderConfiguration) { + build(httpReq, httpResp, (IVelocityGuiBuilderConfiguration) config, contentType, loggerName); + } else { + throw new IllegalStateException(this.getClass().getName() + " needs a " + + IVelocityGuiBuilderConfiguration.class.getName()); + } + + } + + @Override + public void build(final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final IVelocityGuiBuilderConfiguration config, final String loggerName) + throws GuiBuildException { + build(httpReq, httpResp, config, getInternalContentType(config), loggerName); + + } + + @Override + public void build(final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final IVelocityGuiBuilderConfiguration config, final String contentType, + final String loggerName) throws GuiBuildException { + + InputStream is = null; + try { + final String viewName = config.getViewName(); + is = getTemplateInputStream(config); + + // build Velocity Context from input paramters + final VelocityContext context = buildContextFromViewParams(config.getViewParameters()); + + // evaluate template + final StringWriter writer = new StringWriter(); + engine.evaluate(context, writer, loggerName, new BufferedReader(new InputStreamReader(is, "UTF-8"))); + + // write template to response + final byte[] content = writer.toString().getBytes("UTF-8"); + httpResp.setStatus(HttpServletResponse.SC_OK); + httpResp.setContentLength(content.length); + httpResp.setContentType(contentType); + httpResp.getOutputStream().write(content); + + if (log.isTraceEnabled()) { + log.trace("Write Content for viewName:" + viewName + ". Contentsize:" + + String.valueOf(content.length) + " BufferSize:" + httpResp.getBufferSize() + + " ContentType:" + contentType); + for (final String el : httpResp.getHeaderNames()) { + log.trace(" * Headername:" + el + " Value:" + httpResp.getHeader(el)); + } + + } + + } catch (final IOException e) { + log.error("GUI form-builder has an internal error.", e); + throw new GuiBuildException("GUI form-builder has an internal error.", e); + + } finally { + if (is != null) { + try { + is.close(); + + } catch (final IOException e) { + log.error("Can NOT close GUI-Template InputStream.", e); + + } + } + } + + } + + /** + * Generate a new {@link VelocityContext} and populate it with MOA-ID GUI parameters. + * + * @param config GUI builder config + * @return Context of Velocity engine + */ + @Override + public VelocityContext generateVelocityContextFromConfiguration( + final IVelocityGuiBuilderConfiguration config) { + return buildContextFromViewParams(config.getViewParameters()); + + } + + /** + * Load the template from different resources. + * + * @param config GUI builder config + * @return An {@link InputStream} but never null. The {@link InputStream} had to be closed be the + * invoking method + * @throws GuiBuildException In case of an error + */ + @Override + public InputStream getTemplateInputStream(final IVelocityGuiBuilderConfiguration config) + throws GuiBuildException { + InputStream is = config.getTemplate(config.getViewName()); + if (is == null) { + log.trace("Loading GUI template:" + config.getViewName() + " from default resources ... "); + is = getInternalTemplate(config); + + if (is == null) { + log.warn("No GUI with viewName:" + config.getViewName() + " FOUND."); + throw new GuiBuildException("No GUI with viewName:" + config.getViewName() + " FOUND."); + + } + } + return is; + + } + + /** + * Load an internal template from default resources. + * + * @param config GUI builder config + * @return Template that should be used + * @throws GuiBuildException in case of an error + */ + protected abstract InputStream getInternalTemplate(IVelocityGuiBuilderConfiguration config) + throws GuiBuildException; + + + protected String getInternalClasspathTemplateDir(final IVelocityGuiBuilderConfiguration config, + final String defaultClassPathDir) { + String dir = config.getClasspathTemplateDir(); + if (dir != null) { + if (!dir.endsWith("/")) { + dir += "/"; + } + + return dir; + + } else { + return defaultClassPathDir; + } + } + + private VelocityContext buildContextFromViewParams(final Map<String, Object> viewParams) { + final VelocityContext context = new VelocityContext(); + + if (viewParams != null) { + final Iterator<Entry<String, Object>> interator = viewParams.entrySet().iterator(); + while (interator.hasNext()) { + final Entry<String, Object> el = interator.next(); + context.put(el.getKey(), el.getValue()); + } + + } + + return context; + } + + private String getInternalContentType(final IGuiBuilderConfiguration config) { + if (StringUtils.isEmpty(config.getDefaultContentType())) { + return DEFAULT_CONTENT_TYPE; + } else { + return config.getDefaultContentType(); + } + + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/velocity/VelocityLogAdapter.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/velocity/VelocityLogAdapter.java index a118d7e1..05cbaf58 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/velocity/VelocityLogAdapter.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/velocity/VelocityLogAdapter.java @@ -1,32 +1,26 @@ -/******************************************************************************* - * 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.gui.velocity; import org.apache.velocity.app.Velocity; +import org.apache.velocity.runtime.RuntimeConstants; import org.apache.velocity.runtime.RuntimeServices; import org.apache.velocity.runtime.log.LogChute; import org.slf4j.Logger; @@ -34,72 +28,78 @@ import org.slf4j.LoggerFactory; public class VelocityLogAdapter implements LogChute { - private static final Logger log = LoggerFactory.getLogger(VelocityLogAdapter.class); - - public VelocityLogAdapter() { - try - { - /* - * register this class as a logger with the Velocity singleton - * (NOTE: this would not work for the non-singleton method.) - */ - Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, this ); - Velocity.init(); - } - catch (Exception e) - { - log.error("Failed to register Velocity logger"); - } - } - - public void init(RuntimeServices arg0) throws Exception { - } + private static final Logger log = LoggerFactory.getLogger(VelocityLogAdapter.class); + + /** + * VeloCity Logging adapter. + * + */ + public VelocityLogAdapter() { + try { + /* + * register this class as a logger with the Velocity singleton (NOTE: this would not work for + * the non-singleton method.) + */ + Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, this); + Velocity.init(); + } catch (final Exception e) { + log.error("Failed to register Velocity logger"); + } + } + + @Override + public void init(final RuntimeServices arg0) throws Exception { + + } + + @Override + public boolean isLevelEnabled(final int arg0) { + switch (arg0) { + case LogChute.DEBUG_ID: + return log.isDebugEnabled(); + case LogChute.TRACE_ID: + return log.isTraceEnabled(); + default: + return true; + } + } - public boolean isLevelEnabled(int arg0) { - switch(arg0) { - case LogChute.DEBUG_ID: - return log.isDebugEnabled(); - case LogChute.TRACE_ID: - return log.isTraceEnabled(); - default: - return true; - } - } + @Override + public void log(final int arg0, final String arg1) { + switch (arg0) { + case LogChute.DEBUG_ID: + log.debug(arg1); + break; + case LogChute.TRACE_ID: + log.trace(arg1); + break; + case LogChute.INFO_ID: + log.info(arg1); + break; + case LogChute.WARN_ID: + log.warn(arg1); + break; + case LogChute.ERROR_ID: + default: + log.error(arg1); + break; + } + } - public void log(int arg0, String arg1) { - switch(arg0) { - case LogChute.DEBUG_ID: - log.debug(arg1); - break; - case LogChute.TRACE_ID: - log.trace(arg1); - break; - case LogChute.INFO_ID: - log.info(arg1); - break; - case LogChute.WARN_ID: - log.warn(arg1); - break; - case LogChute.ERROR_ID: - default: - log.error(arg1); - break; - } - } + @Override + public void log(final int arg0, final String arg1, final Throwable arg2) { + switch (arg0) { + case LogChute.DEBUG_ID: + case LogChute.TRACE_ID: + case LogChute.INFO_ID: + case LogChute.WARN_ID: + log.warn(arg1, arg2); + break; + case LogChute.ERROR_ID: + default: + log.error(arg1, arg2); + break; + } + } - public void log(int arg0, String arg1, Throwable arg2) { - switch(arg0) { - case LogChute.DEBUG_ID: - case LogChute.TRACE_ID: - case LogChute.INFO_ID: - case LogChute.WARN_ID: - log.warn(arg1, arg2); - break; - case LogChute.ERROR_ID: - default: - log.error(arg1, arg2); - break; - } - } - } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/velocity/VelocityProvider.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/velocity/VelocityProvider.java index 5775e203..18594985 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/velocity/VelocityProvider.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/velocity/VelocityProvider.java @@ -1,121 +1,91 @@ -/******************************************************************************* - * 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 2011 by Graz University of Technology, Austria - * The Austrian STORK Modules have been developed by the E-Government - * Innovation Center EGIZ, a joint initiative of the Federal Chancellery - * Austria 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.gui.velocity; -import org.apache.velocity.app.Velocity; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; /** - * Gets a Velocity Engine - * + * Gets a Velocity Engine. + * * @author bzwattendorfer * */ public class VelocityProvider { - private static VelocityEngine velocityEngine = null; - - /** - * Gets velocityEngine from Classpath - * @return VelocityEngine - * @throws Exception - */ - public static VelocityEngine getClassPathVelocityEngine() throws Exception { - if (velocityEngine == null) { - velocityEngine = getBaseVelocityEngine(); - velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); - velocityEngine.setProperty("classpath.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); - velocityEngine.init(); - - } - - return velocityEngine; - } - - /** - * Gets VelocityEngine from File - * @param rootPath File Path to template file - * @return VelocityEngine - * @throws Exception - */ - public static VelocityEngine getFileVelocityEngine(String rootPath) throws Exception { - if (velocityEngine == null) { - velocityEngine = getBaseVelocityEngine(); - velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "file"); - velocityEngine.setProperty("file.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.FileResourceLoader"); - velocityEngine.setProperty("file.resource.loader.path", rootPath); - - velocityEngine.init(); - - } - - return velocityEngine; - } - - /** - * Gets a basic VelocityEngine - * @return VelocityEngine - */ - private static VelocityEngine getBaseVelocityEngine() { - VelocityEngine velocityEngine = new VelocityEngine(); - velocityEngine.setProperty(RuntimeConstants.INPUT_ENCODING, "UTF-8"); - velocityEngine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); -// velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, -// "org.apache.velocity.runtime.log.SimpleLog4JLogSystem"); - velocityEngine.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, new VelocityLogAdapter() ); - - return velocityEngine; - } - + private static VelocityEngine velocityEngine = null; + + /** + * Gets velocityEngine from Classpath. + * + * @return VelocityEngine + * @throws Exception In case of an error + */ + public static VelocityEngine getClassPathVelocityEngine() throws Exception { + if (velocityEngine == null) { + velocityEngine = getBaseVelocityEngine(); + velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); + velocityEngine.setProperty("classpath.resource.loader.class", + "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + velocityEngine.init(); + + } + + return velocityEngine; + } + + /** + * Gets VelocityEngine from File. + * + * @param rootPath File Path to template file + * @return VelocityEngine + * @throws Exception in case of an error + */ + public static VelocityEngine getFileVelocityEngine(final String rootPath) throws Exception { + if (velocityEngine == null) { + velocityEngine = getBaseVelocityEngine(); + velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "file"); + velocityEngine.setProperty("file.resource.loader.class", + "org.apache.velocity.runtime.resource.loader.FileResourceLoader"); + velocityEngine.setProperty("file.resource.loader.path", rootPath); + + velocityEngine.init(); + + } + + return velocityEngine; + } + + /** + * Gets a basic VelocityEngine. + * + * @return VelocityEngine + */ + private static VelocityEngine getBaseVelocityEngine() { + final VelocityEngine velocityEngine = new VelocityEngine(); + velocityEngine.setProperty(RuntimeConstants.INPUT_ENCODING, "UTF-8"); + velocityEngine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); + // velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, + // "org.apache.velocity.runtime.log.SimpleLog4JLogSystem"); + velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, new VelocityLogAdapter()); + + return velocityEngine; + } + } 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..a02498b7 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,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; import java.io.Serializable; @@ -35,492 +28,547 @@ 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 at.gv.egiz.eaaf.core.impl.data.Pair; 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; + + + + @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 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) { + 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 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; + } + + + + /** + * 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<>(); + + } + + this.additionalBpks.add(bpk); + } + + 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..74b6a0fb --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/EaafCoreSpringResourceProvider.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; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +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..ea197478 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 @@ -2,120 +2,124 @@ package at.gv.egiz.eaaf.core.impl.idp; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; - +import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions.EID_IDENTITY_STATUS_LEVEL_VALUES; +import at.gv.egiz.eaaf.core.api.idp.IEidAuthData; import org.slf4j.Logger; 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.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 EID_IDENTITY_STATUS_LEVEL_VALUES 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 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 Status of the E-ID + */ + public void setEidStatus(final EID_IDENTITY_STATUS_LEVEL_VALUES 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..7a967d3f 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; @@ -31,340 +24,371 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; - import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.StringEscapeUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -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.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; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; 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, 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(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 httpResp http response + * @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 HttpServletResponse httpResp, 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 request http request + * @param response http response + * @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 HttpServletRequest request, + final HttpServletResponse response, 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..1afa879f 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,218 +1,224 @@ -/******************************************************************************* - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.auth; + * 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. + */ -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; +package at.gv.egiz.eaaf.core.impl.idp.auth; 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; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; @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..491fdf4a 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; @@ -32,18 +25,6 @@ import java.io.InputStream; 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; @@ -51,674 +32,748 @@ 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 + */ + private void buildInternalAuthDataGeneric(@NonNull final IAuthData authData, + @NonNull final IAuthProcessDataContainer authProcessData, + @NonNull final IRequest pendingReq) { + Assert.notNull(pendingReq, "PendingRequest is null"); + Assert.notNull(authData, "AuthData is null"); + Assert.notNull(authProcessData, "AuthProcessData is null"); + + if (!(authData instanceof AuthenticationData)) { + log.error("AuthData has no suitable type! Requires: {}", AuthenticationData.class.getName()); + throw new RuntimeException( + "AuthData has no suitable type! Requires: " + AuthenticationData.class.getName()); + + } + + final AuthenticationData internalAuthData = (AuthenticationData) authData; + + // TODO: check if it is needed + // if (authProcessData.getGenericSessionDataStorage() != null && + // !authProcessData.getGenericSessionDataStorage().isEmpty()) + // includedToGenericAuthData = authProcessData.getGenericSessionDataStorage().keySet(); + // else + includedToGenericAuthData = new ArrayList<>(); + + // #################################################### + // set general authData info's + internalAuthData.setAuthenticationIssuer(pendingReq.getAuthUrl()); + internalAuthData.setSsoSession(pendingReq.needSingleSignOnFunctionality()); + internalAuthData.setBaseIdTransferRestrication( + pendingReq.getServiceProviderConfiguration().hasBaseIdTransferRestriction()); + + // #################################################### + // set MDS and vSZ + internalAuthData.setFamilyName(authProcessData + .getGenericDataFromSession(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, 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 authData Current authentication data + * @param authProcessData Authentication information holder from current pending request + * @param pendingReq Current pending request + */ + private void setCitizenCountryCode(final AuthenticationData authData, + final IAuthProcessDataContainer authProcessData, final 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 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, + @NonNull final 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); + + } + + } + + + private void setFlagForeigner(final AuthenticationData authData, + final IAuthProcessDataContainer authProcessData, final 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 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 { + + 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, 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(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..765a6669 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/BpkBuilder.java @@ -0,0 +1,312 @@ +/* + * 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 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; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Base64Utils; + +/** + * 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..7c143ca2 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,24 +1,20 @@ /******************************************************************************* - * 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. *******************************************************************************/ /******************************************************************************* *******************************************************************************/ @@ -29,226 +25,276 @@ package at.gv.egiz.eaaf.core.impl.idp.auth.data; import java.util.Date; import java.util.HashMap; import java.util.Map; - +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#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()); + + } + } } 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..a1faa0a4 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,306 +1,375 @@ /******************************************************************************* - * 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 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 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/ + * 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; - 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; +import org.w3c.dom.Element; /** - * 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; + /** + * family name + */ + private String familyName; + + /** + * date of birth + */ + private String dateOfBirth; /** * the original saml:Assertion-Element */ - private Element samlAssertion; + 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 transient Element prPerson = null; + /** + * we need for each dsig:Reference Element all transformation elements */ - private Element[] dsigReferenceTransforms; - + 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 String getSerializedSamlAssertion() { + 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() { 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..220469d3 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,46 +1,36 @@ /******************************************************************************* - * 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 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 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/ + * 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. */ @@ -50,22 +40,19 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; - -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.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; +import org.springframework.util.Base64Utils; +import org.w3c.dom.Element; +import org.w3c.dom.traversal.NodeIterator; /** - * 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 { @@ -79,246 +66,163 @@ public class SimpleIdentityLinkAssertionParser { 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 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"; + 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 */ + 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"; + 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"; + 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 RSAKeyValue element */ - private static final String RSA_KEY_VALUE_XPATH = - ROOT - + SAML - + "AttributeStatement/" - + SAML - + "Attribute/" - + SAML - + "AttributeValue/" - + DSIG - + "RSAKeyValue"; + /** 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 ECKeyValue element */ - private static final String ECDSA_KEY_VALUE_XPATH = - ROOT - + SAML - + "AttributeStatement/" - + SAML - + "Attribute/" - + SAML - + "AttributeValue/" - + ECDSA - + "ECDSAKeyValue"; + /** The IssueInstant attribute of the SAML assertion */ + private static final String ISSUE_INSTANT_ATTR = "IssueInstant"; - - /** 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*/ + public static final String ASSERTIONID = "AssertionID"; + + /** 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> + * * @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 + */ 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..c785e1cb 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; @@ -34,21 +27,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.lang3.ArrayUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -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; @@ -56,216 +36,233 @@ 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; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.lang3.ArrayUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ResourceLoader; /** - * 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..b04b000e 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,43 +1,38 @@ -/******************************************************************************* - * 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; import java.util.ServiceLoader; - import javax.annotation.PostConstruct; - +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.idp.auth.modules.AuthModule; +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.impl.idp.process.ProcessDefinitionParserException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,135 +40,124 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.core.io.Resource; -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.api.idp.auth.modules.AuthModule; -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.impl.idp.process.ProcessDefinitionParserException; - /** - * This class handles registering modules. The modules are detected either with - * the ServiceLoader mechanism or via Spring. All detected modules are ranked - * according to their priority. + * This class handles registering modules. The modules are detected either with the ServiceLoader + * mechanism or via Spring. All detected modules are ranked according to their priority. */ 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()); + +// public static ModuleRegistration getInstance() { +// return ctx.; +// } + + 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..a5030851 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; @@ -27,499 +24,518 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; import java.util.List; - import javax.naming.ConfigurationException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.StringUtils; -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.lang.NonNull; -import org.springframework.lang.Nullable; -import org.springframework.stereotype.Service; - 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.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; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +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.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Service; @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..fc36f492 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,82 @@ /* - * 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..505ba137 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,67 +1,60 @@ -/******************************************************************************* - * 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; 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..2908ebdf --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/BpkAttributeBuilder.java @@ -0,0 +1,94 @@ +/* + * 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 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; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Assert; + +@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..8029d769 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidCcsUrl.java @@ -0,0 +1,46 @@ +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..ccc2b4e8 --- /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 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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Base64Utils; + +@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..858baf40 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEidasQaaLevelAttributeBuilder.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.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..e828d11c --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEncryptedSourceIdAttributeBuilder.java @@ -0,0 +1,54 @@ +/* + * 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..a1a245d1 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidEncryptedSourceIdTypeAttributeBuilder.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 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..8f629795 --- /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 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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Base64Utils; + +@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..2f70e3e0 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..04c2b379 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidIssuingNationAttributeBuilder.java @@ -0,0 +1,54 @@ +/* + * 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 org.apache.commons.lang3.StringUtils; + +@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..f5e37792 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSectorForIdAttributeBuilder.java @@ -0,0 +1,57 @@ +/* + * 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; +import org.apache.commons.lang3.StringUtils; + +@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..8ba7f255 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSignerCertificate.java @@ -0,0 +1,78 @@ +/* + * 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.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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Base64Utils; + +@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..fd2d51bb --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/EidSourcePin.java @@ -0,0 +1,61 @@ +/* + * 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.AttributePolicyException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import org.apache.commons.lang3.StringUtils; + +@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..2a02fb05 --- /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..bbd7a06c 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,54 @@ -/******************************************************************************* - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + * 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. + */ -import org.apache.commons.lang3.StringUtils; +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.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; +import org.apache.commons.lang3.StringUtils; + +@PvpMetadata +public class GivenNameAttributeBuilder implements IPvpAttributeBuilder { -@PVPMETADATA -public class GivenNameAttributeBuilder implements IPVPAttributeBuilder { + @Override + public String getName() { + return GIVEN_NAME_NAME; + } - @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 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); - } + @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..bbe9b741 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,54 @@ -/******************************************************************************* - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.idp.builder.attributes; + * 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. +*/ -import org.apache.commons.lang3.StringUtils; +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.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; +import org.apache.commons.lang3.StringUtils; + +@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); + } -@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); - } - } 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..5ff68721 --- /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..86cb1dcc --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpCountryCodeAttributeBuilder.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.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..4b905690 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpFriendlyNameAttributeBuilder.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 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..47e5e8ce --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUniqueIdAttributeBuilder.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 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..ce717862 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/builder/attributes/SpUsesMandates.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.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..e661a2a8 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; @@ -34,201 +27,215 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.Map; import java.util.Properties; - +import at.gv.egiz.eaaf.core.api.idp.IExtendedConfiguration; +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; -import at.gv.egiz.eaaf.core.api.idp.IExtendedConfiguration; -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) { + final String value = getBasicConfiguration(key); + if (value != null) { + return Boolean.parseBoolean(value); + } else { + return false; + } + + } + + + @Override + public boolean getBasicConfigurationBoolean(final String key, final boolean defaultValue) { + final Boolean result = getBasicConfigurationBoolean(key); + if (result != null) { + return result; + } 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..3a6cc67d 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; @@ -32,9 +25,10 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; 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 +39,176 @@ 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) { + final String value = getBasicConfiguration(key); + if (StringUtils.isNotEmpty(value)) { + return Boolean.valueOf(value.trim()); + } else { + return false; + } + } + + @Override + public boolean getBasicConfigurationBoolean(final String key, final 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: + */ + 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.debug("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/conf/SpConfigurationImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/SpConfigurationImpl.java new file mode 100644 index 00000000..07284cd3 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/conf/SpConfigurationImpl.java @@ -0,0 +1,193 @@ +/* + * 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 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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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; + + /** + * Service-provider configuration holder. + * + * @param spConfig Key/value based configuration + * @param authConfig Basic application configuration + */ + public SpConfigurationImpl(final Map<String, String> spConfig, final 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 (final String el : targetAreasWithNoInteralBaseIdRestriction) { + log.trace(" Allow baseID processing for prefix " + el); + } + for (final 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(final String key) { + if (key == null) { + return null; + } else { + return this.spConfiguration.get(key); + } + + } + + @Override + public final String getConfigurationValue(final String key, final String defaultValue) { + final String value = getConfigurationValue(key); + if (value == null) { + return defaultValue; + } else { + return value; + } + } + + + @Override + public final boolean isConfigurationValue(final String key) { + final String value = getConfigurationValue(key); + if (value != null) { + return Boolean.parseBoolean(value); + + } + + return false; + } + + + @Override + public final boolean isConfigurationValue(final String key, final boolean defaultValue) { + final String value = getConfigurationValue(key); + if (value != null) { + return Boolean.parseBoolean(value); + + } + + return defaultValue; + } + + @Override + public final boolean containsConfigurationKey(final 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..7c42f506 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,43 +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. +/* + * 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.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; @@ -47,165 +31,215 @@ 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.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())) + + ")"); + return; + + } + + /** + * 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); + 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 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..9ff468d3 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,119 +1,113 @@ -/******************************************************************************* - * 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.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 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.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; +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; /** * 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..7b350c3b 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,32 +1,34 @@ -/******************************************************************************* - * 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.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - +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.ExceptionContainer; +import at.gv.egiz.eaaf.core.exceptions.EaafException; import org.apache.commons.text.StringEscapeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,114 +37,121 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -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.ExceptionContainer; -import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService; -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..ac0876c4 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; @@ -35,444 +28,459 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; - +import javax.annotation.Nonnull; import javax.servlet.http.HttpServletRequest; - -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 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.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.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()); - - } - +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 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<>(); + + + /** + * 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); + + } + + /** + * 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 final HttpServletRequest req, + @NonNull final IConfigurationWithSP authConfig, @Nullable final 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(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 getProcessInstanceId() { + return this.processInstanceId; + + } + + public final void setUniqueTransactionIdentifier(final String id) { + this.uniqueTransactionIdentifer = id; + + } + + public final void setUniqueSessionIdentifier(final String id) { + this.uniqueSessionIdentifer = 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) { + 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(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()); + } + + } + } 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..3c8fd604 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 @@ -13,77 +13,85 @@ 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.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..7991c093 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,81 +1,79 @@ -/******************************************************************************* - * 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; import javax.servlet.http.HttpServletResponse; - -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.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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; /** + * 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..7a2c5f08 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,121 +1,122 @@ -/******************************************************************************* - * 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; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -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; import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; /** + * 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..619911c1 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; @@ -31,87 +24,88 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; - 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..72ad456f 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; @@ -31,40 +24,38 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; - import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; 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..63ae66d5 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; @@ -32,7 +25,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Objects; - import javax.xml.XMLConstants; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; @@ -48,203 +40,225 @@ import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.SAXException; - import at.gv.egiz.eaaf.core.impl.idp.process.model.EndEvent; import at.gv.egiz.eaaf.core.impl.idp.process.model.ProcessDefinition; import at.gv.egiz.eaaf.core.impl.idp.process.model.ProcessNode; import at.gv.egiz.eaaf.core.impl.idp.process.model.StartEvent; import at.gv.egiz.eaaf.core.impl.idp.process.model.TaskInfo; import at.gv.egiz.eaaf.core.impl.idp.process.model.Transition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.SAXException; /** * Parses an XML representation of a process definition as defined by the respective XML schema. - * <p/ * 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.warn("Ignore unknown event: {}", qname); + break; + } + + } + + break; + default: + log.warn("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..472d6469 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,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; /** * 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..0c4946af 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,55 +1,39 @@ -/******************************************************************************* - * 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; -import org.slf4j.MDC; -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.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; @@ -58,439 +42,491 @@ import at.gv.egiz.eaaf.core.impl.idp.process.model.ProcessNode; import at.gv.egiz.eaaf.core.impl.idp.process.model.StartEvent; import at.gv.egiz.eaaf.core.impl.idp.process.model.TaskInfo; import at.gv.egiz.eaaf.core.impl.idp.process.model.Transition; +import org.apache.commons.collections4.IterableUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; /** - * 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..69683529 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,190 +1,185 @@ -/******************************************************************************* - * 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; import java.util.Date; - +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.impl.idp.process.model.ProcessDefinition; +import at.gv.egiz.eaaf.core.impl.idp.process.support.SecureRandomHolder; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.time.DurationFormatUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; -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..e6bfa480 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,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. +/* + * 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..f1abaef3 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,99 +1,91 @@ -/******************************************************************************* - * 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; 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..06c8cc1a --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/dao/ProcessInstanceStoreDaoImpl.java @@ -0,0 +1,94 @@ +/* + * 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 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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 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..48919ded 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,68 +1,60 @@ -/******************************************************************************* - * 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 org.apache.commons.collections4.CollectionUtils; /** * 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..3ab68266 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,184 +1,177 @@ -/******************************************************************************* - * 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; - 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. * </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..92858edf 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,95 +1,95 @@ -/******************************************************************************* - * 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; 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}. + * * @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..698312c7 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,71 +1,63 @@ -/******************************************************************************* - * 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 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..9e384b4c 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,120 +1,117 @@ -/******************************************************************************* - * 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 org.apache.commons.collections4.CollectionUtils; - import at.gv.egiz.eaaf.core.api.idp.process.Task; +import org.apache.commons.collections4.CollectionUtils; /** * 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..4c7b70f0 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,162 +1,150 @@ -/******************************************************************************* - * 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 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}. - * + * * @author tknall - * + * */ public class Transition implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private String id; - private String conditionExpression; - private ProcessNode from; - private ProcessNode to; + 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; - } + /** + * 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; - } + /** + * 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; - } + /** + * 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; - } + /** + * 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; - } + /** + * 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; - } + /** + * 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; - } + /** + * 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; - } + /** + * 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() { - 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(); - } + @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..fc01463e 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,35 +1,29 @@ -/******************************************************************************* - * 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; - import javax.annotation.PostConstruct; - +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.impl.idp.process.model.Transition; import org.apache.commons.lang3.BooleanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,47 +35,44 @@ import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; -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.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..cc899641 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,34 +1,29 @@ -/******************************************************************************* - * 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; import javax.servlet.http.HttpServletRequest; - +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.impl.idp.process.ProcessInstance; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -36,107 +31,95 @@ import org.springframework.beans.factory.NoUniqueBeanDefinitionException; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; -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.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..02db6686 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,50 +1,42 @@ -/******************************************************************************* - * 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; import javax.servlet.http.HttpServletResponse; - -import org.springframework.web.context.request.RequestAttributes; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import org.springframework.web.filter.RequestContextFilter; - import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.api.idp.process.Task; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.filter.RequestContextFilter; /** - * 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 +49,72 @@ 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}. + * + * <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; + - /** - * 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."); - } - } } 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..c723a728 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,33 @@ -/******************************************************************************* - * 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 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.impl.idp.process.model.Transition; import org.apache.commons.lang3.BooleanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,121 +39,89 @@ import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; -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.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>{@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); + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/logging/DummyRevisionsLogger.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/logging/DummyRevisionsLogger.java index 77af20c8..0c5129bc 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/logging/DummyRevisionsLogger.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/logging/DummyRevisionsLogger.java @@ -1,76 +1,68 @@ -/******************************************************************************* - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.logging; + * 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. +*/ -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package at.gv.egiz.eaaf.core.impl.logging; import at.gv.egiz.eaaf.core.api.IRequest; -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.logging.IRevisionLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DummyRevisionsLogger implements IRevisionLogger { - private static final Logger log = LoggerFactory.getLogger(DummyStatisticLogger.class); - - - @Override - public void logEvent(ISPConfiguration oaConfig, int eventCode, String message) { - log.trace("Dummy-logEventOperation"); + private static final Logger log = LoggerFactory.getLogger(DummyStatisticLogger.class); + + + @Override + public void logEvent(final IspConfiguration oaConfig, final int eventCode, final String message) { + log.trace("Dummy-logEventOperation"); - } + } - @Override - public void logEvent(int eventCode, String message) { - log.trace("Dummy-logEventOperation"); + @Override + public void logEvent(final int eventCode, final String message) { + log.trace("Dummy-logEventOperation"); - } + } - @Override - public void logEvent(String sessionID, String transactionID, int eventCode, String message) { - log.trace("Dummy-logEventOperation"); + @Override + public void logEvent(final String sessionID, final String transactionID, final int eventCode, final String message) { + log.trace("Dummy-logEventOperation"); - } + } - @Override - public void logEvent(String sessionID, String transactionID, int eventCode) { - log.trace("Dummy-logEventOperation"); + @Override + public void logEvent(final String sessionID, final String transactionID, final int eventCode) { + log.trace("Dummy-logEventOperation"); - } + } - @Override - public void logEvent(IRequest pendingRequest, int eventCode) { - log.trace("Dummy-logEventOperation"); + @Override + public void logEvent(final IRequest pendingRequest, final int eventCode) { + log.trace("Dummy-logEventOperation"); - } + } - @Override - public void logEvent(IRequest pendingRequest, int eventCode, String message) { - log.trace("Dummy-logEventOperation"); + @Override + public void logEvent(final IRequest pendingRequest, final int eventCode, final String message) { + log.trace("Dummy-logEventOperation"); - } + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/logging/DummyStatisticLogger.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/logging/DummyStatisticLogger.java index 857186db..3d4a2e5e 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/logging/DummyStatisticLogger.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/logging/DummyStatisticLogger.java @@ -1,67 +1,61 @@ -/******************************************************************************* - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.logging; + * 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.logging; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.IAuthData; import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; -@Service("DummyStatisticLogger") -public class DummyStatisticLogger implements IStatisticLogger{ - private static final Logger log = LoggerFactory.getLogger(DummyStatisticLogger.class); - - @Override - public void logSuccessOperation(IRequest protocolRequest, - IAuthData authData, boolean isSSOSession) { - log.trace("Dummy-logSuccessOperation"); - } - - @Override - public void logErrorOperation(Throwable throwable) { - log.trace("Dummy-logErrorOperation"); - } - - @Override - public void logErrorOperation(Throwable throwable, IRequest errorRequest) { - log.trace("Dummy-logErrorOperation"); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.advancedlogging.IStatisticLogger#testConnection() - */ - @Override - public void internalTesting() throws Exception { - log.trace("Dummy-logErrorOperation"); - - } +@Service("DummyStatisticLogger") +public class DummyStatisticLogger implements IStatisticLogger { + private static final Logger log = LoggerFactory.getLogger(DummyStatisticLogger.class); + + @Override + public void logSuccessOperation(final IRequest protocolRequest, final IAuthData authData, + final boolean isSsoSession) { + log.trace("Dummy-logSuccessOperation"); + } + + @Override + public void logErrorOperation(final Throwable throwable) { + log.trace("Dummy-logErrorOperation"); + } + + @Override + public void logErrorOperation(final Throwable throwable, final IRequest errorRequest) { + log.trace("Dummy-logErrorOperation"); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.advancedlogging.IStatisticLogger#testConnection() + */ + @Override + public void internalTesting() throws Exception { + log.trace("Dummy-logErrorOperation"); + + } } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DOMUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DOMUtils.java deleted file mode 100644 index a9d33b74..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DOMUtils.java +++ /dev/null @@ -1,1267 +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.utils; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.Vector; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Result; -import javax.xml.transform.Source; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.xerces.parsers.DOMParser; -import org.apache.xerces.parsers.SAXParser; -import org.apache.xerces.parsers.XMLGrammarPreparser; -import org.apache.xerces.util.SymbolTable; -import org.apache.xerces.util.XMLGrammarPoolImpl; -import org.apache.xerces.xni.grammars.XMLGrammarDescription; -import org.apache.xerces.xni.grammars.XMLGrammarPool; -import org.apache.xerces.xni.parser.XMLInputSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.DocumentFragment; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.EntityResolver; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants; - -/** - * Various utility functions for handling XML DOM trees. - * - * The parsing methods in this class make use of some features internal to the - * Xerces DOM parser, mainly for performance reasons. As soon as JAXP - * (currently at version 1.2) is better at schema handling, it should be used as - * the parser interface. - * - */ -public class DOMUtils { - private static final Logger log = LoggerFactory.getLogger(DOMUtils.class); - - /** Feature URI for namespace aware parsing. */ - private static final String NAMESPACES_FEATURE = - "http://xml.org/sax/features/namespaces"; - /** Feature URI for validating parsing. */ - private static final String VALIDATION_FEATURE = - "http://xml.org/sax/features/validation"; - /** Feature URI for schema validating parsing. */ - private static final String SCHEMA_VALIDATION_FEATURE = - "http://apache.org/xml/features/validation/schema"; - /** Feature URI for normalization of element/attribute values. */ - private static final String NORMALIZED_VALUE_FEATURE = - "http://apache.org/xml/features/validation/schema/normalized-value"; - /** Feature URI for parsing ignorable whitespace. */ - private static final String INCLUDE_IGNORABLE_WHITESPACE_FEATURE = - "http://apache.org/xml/features/dom/include-ignorable-whitespace"; - /** Feature URI for creating EntityReference nodes in the DOM tree. */ - private static final String CREATE_ENTITY_REF_NODES_FEATURE = - "http://apache.org/xml/features/dom/create-entity-ref-nodes"; - /** Property URI for providing external schema locations. */ - private static final String EXTERNAL_SCHEMA_LOCATION_PROPERTY = - "http://apache.org/xml/properties/schema/external-schemaLocation"; - /** Property URI for providing the external schema location for elements - * without a namespace. */ - private static final String EXTERNAL_NO_NAMESPACE_SCHEMA_LOCATION_PROPERTY = - "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"; - - private static final String EXTERNAL_GENERAL_ENTITIES_FEATURE = - "http://xml.org/sax/features/external-general-entities"; - - private static final String EXTERNAL_PARAMETER_ENTITIES_FEATURE = - "http://xml.org/sax/features/external-parameter-entities"; - - public static final String DISALLOW_DOCTYPE_FEATURE = - "http://apache.org/xml/features/disallow-doctype-decl"; - - - - /** Property URI for the Xerces grammar pool. */ - private static final String GRAMMAR_POOL = - org.apache.xerces.impl.Constants.XERCES_PROPERTY_PREFIX - + org.apache.xerces.impl.Constants.XMLGRAMMAR_POOL_PROPERTY; - /** A prime number for initializing the symbol table. */ - private static final int BIG_PRIME = 2039; - /** Symbol table for the grammar pool. */ - private static SymbolTable symbolTable = new SymbolTable(BIG_PRIME); - /** Xerces schema grammar pool. */ - private static XMLGrammarPool grammarPool = new XMLGrammarPoolImpl(); - /** Set holding the NamespaceURIs of the grammarPool, to prevent multiple - * entries of same grammars to the pool */ - private static Set grammarNamespaces; - - static { - grammarPool.lockPool(); - grammarNamespaces = new HashSet(); - } - - /** - * Preparse a schema and add it to the schema pool. - * The method only adds the schema to the pool if a schema having the same - * <code>systemId</code> (namespace URI) is not already present in the pool. - * - * @param inputStream An <code>InputStream</code> providing the contents of - * the schema. - * @param systemId The systemId (namespace URI) to use for the schema. - * @throws IOException An error occurred reading the schema. - */ - public static void addSchemaToPool(InputStream inputStream, String systemId) - throws IOException { - XMLGrammarPreparser preparser; - - if (!grammarNamespaces.contains(systemId)) { - - grammarNamespaces.add(systemId); - - // unlock the pool so that we can add another grammar - grammarPool.unlockPool(); - - // prepare the preparser - preparser = new XMLGrammarPreparser(symbolTable); - preparser.registerPreparser(XMLGrammarDescription.XML_SCHEMA, null); - preparser.setProperty(GRAMMAR_POOL, grammarPool); - preparser.setFeature(NAMESPACES_FEATURE, true); - preparser.setFeature(VALIDATION_FEATURE, true); - - // add the grammar to the pool - preparser.preparseGrammar( - XMLGrammarDescription.XML_SCHEMA, - new XMLInputSource(null, systemId, null, inputStream, null)); - - // lock the pool again so that schemas are not added automatically - grammarPool.lockPool(); - } - } - - /** - * Parse an XML document from an <code>InputStream</code>. - * - * @param inputStream The <code>InputStream</code> containing the XML - * document. - * @param validating If <code>true</code>, parse validating. - * @param externalSchemaLocations A <code>String</code> containing namespace - * URI to schema location pairs, the same way it is accepted by the <code>xsi: - * schemaLocation</code> attribute. - * @param externalNoNamespaceSchemaLocation The schema location of the - * schema for elements without a namespace, the same way it is accepted by the - * <code>xsi:noNamespaceSchemaLocation</code> attribute. - * @param entityResolver An <code>EntityResolver</code> to resolve external - * entities (schemas and DTDs). If <code>null</code>, it will not be set. - * @param errorHandler An <code>ErrorHandler</code> to decide what to do - * with parsing errors. If <code>null</code>, it will not be set. - * @return The parsed XML document as a DOM tree. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document. - * @throws ParserConfigurationException An error occurred configuring the XML - * parser. - */ - public static Document parseDocument( - InputStream inputStream, - boolean validating, - String externalSchemaLocations, - String externalNoNamespaceSchemaLocation, - EntityResolver entityResolver, - ErrorHandler errorHandler, - Map<String, Object> parserFeatures) - throws SAXException, IOException, ParserConfigurationException { - - DOMParser parser; - -// class MyEntityResolver implements EntityResolver { -// -// public InputSource resolveEntity(String publicId, String systemId) -// throws SAXException, IOException { -// return new InputSource(new ByteArrayInputStream(new byte[0])); -// } -// } - - - //if Debug is enabled make a copy of inputStream to enable debug output in case of SAXException - byte buffer [] = null; - ByteArrayInputStream baStream = null; - if(true == log.isDebugEnabled()) { - buffer = IOUtils.toByteArray(inputStream); - baStream = new ByteArrayInputStream(buffer); - - } - - - - // create the DOM parser - if (symbolTable != null) { - parser = new DOMParser(symbolTable, grammarPool); - } else { - parser = new DOMParser(); - } - - // set parser features and properties - try { - parser.setFeature(NAMESPACES_FEATURE, true); - parser.setFeature(VALIDATION_FEATURE, validating); - parser.setFeature(SCHEMA_VALIDATION_FEATURE, validating); - parser.setFeature(NORMALIZED_VALUE_FEATURE, false); - parser.setFeature(INCLUDE_IGNORABLE_WHITESPACE_FEATURE, true); - parser.setFeature(CREATE_ENTITY_REF_NODES_FEATURE, false); - parser.setFeature(EXTERNAL_GENERAL_ENTITIES_FEATURE, false); - parser.setFeature(EXTERNAL_PARAMETER_ENTITIES_FEATURE, false); - - //set external added parser features - if (parserFeatures != null) { - for (Entry<String, Object> el : parserFeatures.entrySet()) { - String key = el.getKey(); - if (StringUtils.isNotEmpty(key)) { - Object value = el.getValue(); - if (value != null && value instanceof Boolean) - parser.setFeature(key, (boolean)value); - - else - log.warn("This XML parser only allows features with 'boolean' values"); - - } else - log.warn("Can not set 'null' feature to XML parser"); - } - } - - //fix XXE problem - //parser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - - - if (validating) { - if (externalSchemaLocations != null) { - parser.setProperty( - EXTERNAL_SCHEMA_LOCATION_PROPERTY, - externalSchemaLocations); - } - if (externalNoNamespaceSchemaLocation != null) { - parser.setProperty( - EXTERNAL_NO_NAMESPACE_SCHEMA_LOCATION_PROPERTY, - externalNoNamespaceSchemaLocation); - } - } - - // set entity resolver and error handler - if (entityResolver != null) { - parser.setEntityResolver(entityResolver); - } - if (errorHandler != null) { - parser.setErrorHandler(errorHandler); - } - - // parse the document and return it - // if debug is enabled: use copy of strem (baStream) else use orig stream - if(null != baStream) - parser.parse(new InputSource(baStream)); - else - parser.parse(new InputSource(inputStream)); - } catch(SAXException e) { - if(true == log.isDebugEnabled() && null != buffer) { - String xmlContent = new String(buffer); - log.debug("SAXException in:\n" + xmlContent); - } - throw(e); - } - - return parser.getDocument(); - } - - /** - * Parse an XML document from an <code>InputStream</code>. - * - * @param inputStream The <code>InputStream</code> containing the XML - * document. - * @param validating If <code>true</code>, parse validating. - * @param externalSchemaLocations A <code>String</code> containing namespace - * URI to schema location pairs, the same way it is accepted by the <code>xsi: - * schemaLocation</code> attribute. - * @param externalNoNamespaceSchemaLocation The schema location of the - * schema for elements without a namespace, the same way it is accepted by the - * <code>xsi:noNamespaceSchemaLocation</code> attribute. - * @param entityResolver An <code>EntityResolver</code> to resolve external - * entities (schemas and DTDs). If <code>null</code>, it will not be set. - * @param errorHandler An <code>ErrorHandler</code> to decide what to do - * with parsing errors. If <code>null</code>, it will not be set. - * @return The parsed XML document as a DOM tree. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document. - * @throws ParserConfigurationException An error occurred configuring the XML - * parser. - */ - public static Document parseDocumentSimple(InputStream inputStream) - throws SAXException, IOException, ParserConfigurationException { - - DOMParser parser; - - parser = new DOMParser(); - // set parser features and properties - parser.setFeature(NAMESPACES_FEATURE, true); - parser.setFeature(VALIDATION_FEATURE, false); - parser.setFeature(SCHEMA_VALIDATION_FEATURE, false); - parser.setFeature(NORMALIZED_VALUE_FEATURE, false); - parser.setFeature(INCLUDE_IGNORABLE_WHITESPACE_FEATURE, true); - parser.setFeature(CREATE_ENTITY_REF_NODES_FEATURE, false); - - parser.parse(new InputSource(inputStream)); - - return parser.getDocument(); - } - - - /** - * Parse an XML document from an <code>InputStream</code>. - * - * It uses a <code>MOAEntityResolver</code> as the <code>EntityResolver</code> - * and a <code>MOAErrorHandler</code> as the <code>ErrorHandler</code>. - * - * @param inputStream The <code>InputStream</code> containing the XML - * document. - * @param validating If <code>true</code>, parse validating. - * @param externalSchemaLocations A <code>String</code> containing namespace - * URI to schema location pairs, the same way it is accepted by the <code>xsi: - * schemaLocation</code> attribute. - * @param externalNoNamespaceSchemaLocation The schema location of the - * schema for elements without a namespace, the same way it is accepted by the - * <code>xsi:noNamespaceSchemaLocation</code> attribute. - * @param parserFeatures - * @return The parsed XML document as a DOM tree. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document. - * @throws ParserConfigurationException An error occurred configuring the XML - * parser. - */ - public static Document parseDocument( - InputStream inputStream, - boolean validating, - String externalSchemaLocations, - String externalNoNamespaceSchemaLocation, Map<String, Object> parserFeatures) - throws SAXException, IOException, ParserConfigurationException { - - - - return parseDocument( - inputStream, - validating, - externalSchemaLocations, - externalNoNamespaceSchemaLocation, - new EAAFDomEntityResolver(), - null, - parserFeatures); - } - - /** - * Parse an XML document from a <code>String</code>. - * - * It uses a <code>MOAEntityResolver</code> as the <code>EntityResolver</code> - * and a <code>MOAErrorHandler</code> as the <code>ErrorHandler</code>. - * - * @param xmlString The <code>String</code> containing the XML document. - * @param encoding The encoding of the XML document. - * @param validating If <code>true</code>, parse validating. - * @param externalSchemaLocations A <code>String</code> containing namespace - * URI to schema location pairs, the same way it is accepted by the <code>xsi: - * schemaLocation</code> attribute. - * @param externalNoNamespaceSchemaLocation The schema location of the - * schema for elements without a namespace, the same way it is accepted by the - * <code>xsi:noNamespaceSchemaLocation</code> attribute. - * @return The parsed XML document as a DOM tree. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document. - * @throws ParserConfigurationException An error occurred configuring the XML - * parser. - */ - public static Document parseDocument( - String xmlString, - String encoding, - boolean validating, - String externalSchemaLocations, - String externalNoNamespaceSchemaLocation, - Map<String, Object> parserFeatures) - throws SAXException, IOException, ParserConfigurationException { - - InputStream in = new ByteArrayInputStream(xmlString.getBytes(encoding)); - return parseDocument( - in, - validating, - externalSchemaLocations, - externalNoNamespaceSchemaLocation, - parserFeatures); - } - - - /** - * Parse an XML document from a <code>String</code>. - * - * It uses a <code>MOAEntityResolver</code> as the <code>EntityResolver</code> - * and a <code>MOAErrorHandler</code> as the <code>ErrorHandler</code>. - * - * @param xmlString The <code>String</code> containing the XML document. - * @param encoding The encoding of the XML document. - * @param validating If <code>true</code>, parse validating. - * @param externalSchemaLocations A <code>String</code> containing namespace - * URI to schema location pairs, the same way it is accepted by the <code>xsi: - * schemaLocation</code> attribute. - * @param externalNoNamespaceSchemaLocation The schema location of the - * schema for elements without a namespace, the same way it is accepted by the - * <code>xsi:noNamespaceSchemaLocation</code> attribute. - * @return The parsed XML document as a DOM tree. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document. - * @throws ParserConfigurationException An error occurred configuring the XML - * parser. - */ - public static Document parseDocument( - String xmlString, - String encoding, - boolean validating, - String externalSchemaLocations, - String externalNoNamespaceSchemaLocation) - throws SAXException, IOException, ParserConfigurationException { - - InputStream in = new ByteArrayInputStream(xmlString.getBytes(encoding)); - return parseDocument( - in, - validating, - externalSchemaLocations, - externalNoNamespaceSchemaLocation, - null); - } - - /** - * Parse an UTF-8 encoded XML document from a <code>String</code>. - * - * @param xmlString The <code>String</code> containing the XML document. - * @param validating If <code>true</code>, parse validating. - * @param externalSchemaLocations A <code>String</code> containing namespace - * URI to schema location pairs, the same way it is accepted by the <code>xsi: - * schemaLocation</code> attribute. - * @param externalNoNamespaceSchemaLocation The schema location of the - * schema for elements without a namespace, the same way it is accepted by the - * <code>xsi:noNamespaceSchemaLocation</code> attribute. - * @return The parsed XML document as a DOM tree. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document. - * @throws ParserConfigurationException An error occurred configuring the XML - * parser. - */ - public static Document parseDocument( - String xmlString, - boolean validating, - String externalSchemaLocations, - String externalNoNamespaceSchemaLocation) - throws SAXException, IOException, ParserConfigurationException { - - return parseDocument( - xmlString, - "UTF-8", - validating, - externalSchemaLocations, - externalNoNamespaceSchemaLocation); - } - - /** - * A convenience method to parse an XML document validating. - * - * @param inputStream The <code>InputStream</code> containing the XML - * document. - * @return The root element of the parsed XML document. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document. - * @throws ParserConfigurationException An error occurred configuring the XML - * parser. - */ - public static Element parseXmlValidating(InputStream inputStream) - throws ParserConfigurationException, SAXException, IOException { - return DOMUtils - .parseDocument(inputStream, true, XMLNamespaceConstants.ALL_SCHEMA_LOCATIONS, null, null) - .getDocumentElement(); - } - - /** - * A convenience method to parse an XML document validating. - * - * @param inputStream The <code>InputStream</code> containing the XML - * document. - * @param parserFeatures Set additional features to XML parser - * @return The root element of the parsed XML document. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document. - * @throws ParserConfigurationException An error occurred configuring the XML - * parser. - */ - public static Element parseXmlValidating(InputStream inputStream, Map<String, Object> parserFeatures) - throws ParserConfigurationException, SAXException, IOException { - return DOMUtils - .parseDocument(inputStream, true, XMLNamespaceConstants.ALL_SCHEMA_LOCATIONS, null, parserFeatures) - .getDocumentElement(); - } - - /** - * A convenience method to parse an XML document non validating. - * This method disallow DocType declarations - * - * @param inputStream The <code>InputStream</code> containing the XML - * document. - * @return The root element of the parsed XML document. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document. - * @throws ParserConfigurationException An error occurred configuring the XML - * parser. - */ - public static Element parseXmlNonValidating(InputStream inputStream) - throws ParserConfigurationException, SAXException, IOException { - return DOMUtils - .parseDocument(inputStream, false, XMLNamespaceConstants.ALL_SCHEMA_LOCATIONS, null, - Collections.unmodifiableMap(new HashMap<String, Object>() { - private static final long serialVersionUID = 1L; - { - put(DOMUtils.DISALLOW_DOCTYPE_FEATURE, true); - - } - })).getDocumentElement(); - } - - /** - * Schema validate a given DOM element. - * - * @param element The element to validate. - * @param externalSchemaLocations A <code>String</code> containing namespace - * URI to schema location pairs, the same way it is accepted by the <code>xsi: - * schemaLocation</code> attribute. - * @param externalNoNamespaceSchemaLocation The schema location of the - * schema for elements without a namespace, the same way it is accepted by the - * <code>xsi:noNamespaceSchemaLocation</code> attribute. - * @return <code>true</code>, if the <code>element</code> validates against - * the schemas declared in it. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document from its - * serialized representation. - * @throws ParserConfigurationException An error occurred configuring the XML - * @throws TransformerException An error occurred serializing the element. - */ - public static boolean validateElement( - Element element, - String externalSchemaLocations, - String externalNoNamespaceSchemaLocation) - throws - ParserConfigurationException, - IOException, - SAXException, - TransformerException { - - byte[] docBytes; - SAXParser parser; - - // create the SAX parser - if (symbolTable != null) { - parser = new SAXParser(symbolTable, grammarPool); - } else { - parser = new SAXParser(); - } - - // serialize the document - docBytes = serializeNode(element, "UTF-8"); - - // set up parser features and attributes - parser.setFeature(NAMESPACES_FEATURE, true); - parser.setFeature(VALIDATION_FEATURE, true); - parser.setFeature(SCHEMA_VALIDATION_FEATURE, true); - parser.setFeature(EXTERNAL_GENERAL_ENTITIES_FEATURE, false); - parser.setFeature(DISALLOW_DOCTYPE_FEATURE, true); - - - if (externalSchemaLocations != null) { - parser.setProperty( - EXTERNAL_SCHEMA_LOCATION_PROPERTY, - externalSchemaLocations); - } - if (externalNoNamespaceSchemaLocation != null) { - parser.setProperty( - EXTERNAL_NO_NAMESPACE_SCHEMA_LOCATION_PROPERTY, - "externalNoNamespaceSchemaLocation"); - } - - // set up entity resolver and error handler - parser.setEntityResolver(new EAAFDomEntityResolver()); - - // parse validating - parser.parse(new InputSource(new ByteArrayInputStream(docBytes))); - return true; - } - - - /** - * Schema validate a given DOM element. - * - * @param element The element to validate. - * @param externalSchemaLocations A <code>String</code> containing namespace - * URI to schema location pairs, the same way it is accepted by the <code>xsi: - * schemaLocation</code> attribute. - * @param externalNoNamespaceSchemaLocation The schema location of the - * schema for elements without a namespace, the same way it is accepted by the - * <code>xsi:noNamespaceSchemaLocation</code> attribute. - * @return <code>true</code>, if the <code>element</code> validates against - * the schemas declared in it. - * @throws SAXException An error occurred parsing the document. - * @throws IOException An error occurred reading the document from its - * serialized representation. - * @throws ParserConfigurationException An error occurred configuring the XML - * @throws TransformerException An error occurred serializing the element. - */ - public static boolean validateElement( - Element element, - String externalSchemaLocations, - String externalNoNamespaceSchemaLocation, - EntityResolver entityResolver) - throws - ParserConfigurationException, - IOException, - SAXException, - TransformerException { - - byte[] docBytes; - SAXParser parser; - - // create the SAX parser - if (symbolTable != null) { - parser = new SAXParser(symbolTable, grammarPool); - } else { - parser = new SAXParser(); - } - - // serialize the document - docBytes = serializeNode(element, "UTF-8"); - - // set up parser features and attributes - parser.setFeature(NAMESPACES_FEATURE, true); - parser.setFeature(VALIDATION_FEATURE, true); - parser.setFeature(SCHEMA_VALIDATION_FEATURE, true); - - if (externalSchemaLocations != null) { - parser.setProperty( - EXTERNAL_SCHEMA_LOCATION_PROPERTY, - externalSchemaLocations); - } - if (externalNoNamespaceSchemaLocation != null) { - parser.setProperty( - EXTERNAL_NO_NAMESPACE_SCHEMA_LOCATION_PROPERTY, - "externalNoNamespaceSchemaLocation"); - } - - // set up entity resolver and error handler - parser.setEntityResolver(entityResolver); - - // parse validating - parser.parse(new InputSource(new ByteArrayInputStream(docBytes))); - return true; - } - - /** - * Serialize the given DOM node. - * - * The node will be serialized using the UTF-8 encoding. - * - * @param node The node to serialize. - * @return String The <code>String</code> representation of the given DOM - * node. - * @throws TransformerException An error occurred transforming the - * node to a <code>String</code>. - * @throws IOException An IO error occurred writing the node to a byte array. - */ - public static String serializeNode(Node node) - throws TransformerException, IOException { - return new String(serializeNode(node, "UTF-8", false), "UTF-8"); - } - - - /** - * Serialize the given DOM node. - * - * The node will be serialized using the UTF-8 encoding. - * - * @param node The node to serialize. - * @param omitXmlDeclaration The boolean value for omitting the XML Declaration. - * @return String The <code>String</code> representation of the given DOM - * node. - * @throws TransformerException An error occurred transforming the - * node to a <code>String</code>. - * @throws IOException An IO error occurred writing the node to a byte array. - */ - public static String serializeNode(Node node, boolean omitXmlDeclaration) - throws TransformerException, IOException { - return new String(serializeNode(node, "UTF-8", omitXmlDeclaration), "UTF-8"); - } - - /** - * Serialize the given DOM node. - * - * The node will be serialized using the UTF-8 encoding. - * - * @param node The node to serialize. - * @param omitXmlDeclaration The boolean value for omitting the XML Declaration. - * @param lineSeperator Sets the line seperator String of the parser - * @return String The <code>String</code> representation of the given DOM - * node. - * @throws TransformerException An error occurred transforming the - * node to a <code>String</code>. - * @throws IOException An IO error occurred writing the node to a byte array. - */ - public static String serializeNode(Node node, boolean omitXmlDeclaration, String lineSeperator) - throws TransformerException, IOException { - return new String(serializeNode(node, "UTF-8", omitXmlDeclaration, lineSeperator), "UTF-8"); - } - - /** - * Serialize the given DOM node to a byte array. - * - * @param node The node to serialize. - * @param xmlEncoding The XML encoding to use. - * @return The serialized node, as a byte array. Using a compatible encoding - * this can easily be converted into a <code>String</code>. - * @throws TransformerException An error occurred transforming the node to a - * byte array. - * @throws IOException An IO error occurred writing the node to a byte array. - */ - public static byte[] serializeNode(Node node, String xmlEncoding) - throws TransformerException, IOException { - return serializeNode(node, xmlEncoding, false); - } - - /** - * Serialize the given DOM node to a byte array. - * - * @param node The node to serialize. - * @param xmlEncoding The XML encoding to use. - * @param omitDeclaration The boolean value for omitting the XML Declaration. - * @return The serialized node, as a byte array. Using a compatible encoding - * this can easily be converted into a <code>String</code>. - * @throws TransformerException An error occurred transforming the node to a - * byte array. - * @throws IOException An IO error occurred writing the node to a byte array. - */ - public static byte[] serializeNode(Node node, String xmlEncoding, boolean omitDeclaration) - throws TransformerException, IOException { - return serializeNode(node, xmlEncoding, omitDeclaration, null); - } - - - /** - * Serialize the given DOM node to a byte array. - * - * @param node The node to serialize. - * @param xmlEncoding The XML encoding to use. - * @param omitDeclaration The boolean value for omitting the XML Declaration. - * @param lineSeperator Sets the line seperator String of the parser - * @return The serialized node, as a byte array. Using a compatible encoding - * this can easily be converted into a <code>String</code>. - * @throws TransformerException An error occurred transforming the node to a - * byte array. - * @throws IOException An IO error occurred writing the node to a byte array. - */ - public static byte[] serializeNode(Node node, String xmlEncoding, boolean omitDeclaration, String lineSeperator) - throws TransformerException, IOException { - - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(16384); - - transformer.setOutputProperty(OutputKeys.METHOD, "xml"); - transformer.setOutputProperty(OutputKeys.ENCODING, xmlEncoding); - String omit = omitDeclaration ? "yes" : "no"; - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, omit); - if (null!=lineSeperator) { - transformer.setOutputProperty("{http://xml.apache.org/xalan}line-separator", lineSeperator);//does not work for xalan <= 2.5.1 - } - transformer.transform(new DOMSource(node), new StreamResult(bos)); - - bos.flush(); - bos.close(); - - return bos.toByteArray(); - } - - /** - * Return the text that a node contains. - * - * This routine: - * <ul> - * <li>Ignores comments and processing instructions.</li> - * <li>Concatenates TEXT nodes, CDATA nodes, and the results recursively - * processing EntityRef nodes.</li> - * <li>Ignores any element nodes in the sublist. (Other possible options are - * to recurse into element sublists or throw an exception.)</li> - * </ul> - * - * @param node A DOM node from which to extract text. - * @return A String representing its contents. - */ - public static String getText(Node node) { - if (!node.hasChildNodes()) { - return ""; - } - - StringBuffer result = new StringBuffer(); - NodeList list = node.getChildNodes(); - - for (int i = 0; i < list.getLength(); i++) { - Node subnode = list.item(i); - if (subnode.getNodeType() == Node.TEXT_NODE) { - result.append(subnode.getNodeValue()); - } else if (subnode.getNodeType() == Node.CDATA_SECTION_NODE) { - result.append(subnode.getNodeValue()); - } else if (subnode.getNodeType() == Node.ENTITY_REFERENCE_NODE) { - // Recurse into the subtree for text - // (and ignore comments) - result.append(getText(subnode)); - } - } - return result.toString(); - } - - /** - * Build the namespace prefix to namespace URL mapping in effect for a given - * node. - * - * @param node The context node for which build the map. - * @return The namespace prefix to namespace URL mapping ( - * a <code>String</code> value to <code>String</code> value mapping). - */ - public static Map getNamespaceDeclarations(Node node) { - Map nsDecls = new HashMap(); - int i; - - do { - if (node.hasAttributes()) { - NamedNodeMap attrs = node.getAttributes(); - - for (i = 0; i < attrs.getLength(); i++) { - Attr attr = (Attr) attrs.item(i); - - // add prefix mapping if none exists - if ("xmlns".equals(attr.getPrefix()) - || "xmlns".equals(attr.getName())) { - - String nsPrefix = - attr.getPrefix() != null ? attr.getLocalName() : ""; - - if (nsDecls.get(nsPrefix) == null) { - nsDecls.put(nsPrefix, attr.getValue()); - } - } - } - } - } while ((node = node.getParentNode()) != null); - - return nsDecls; - } - - /** - * Add all namespace declarations declared in the parent(s) of a given - * element and used in the subtree of the given element to the given element. - * - * @param context The element to which to add the namespaces. - */ - public static void localizeNamespaceDeclarations(Element context) { - Node parent = context.getParentNode(); - - if (parent != null) { - Map namespaces = getNamespaceDeclarations(context.getParentNode()); - Set nsUris = collectNamespaceURIs(context); - Iterator iter; - - for (iter = namespaces.entrySet().iterator(); iter.hasNext();) { - Map.Entry e = (Map.Entry) iter.next(); - - if (nsUris.contains(e.getValue())) { - String prefix = (String) e.getKey(); - String nsUri = (String) e.getValue(); - String nsAttrName = "".equals(prefix) ? "xmlns" : "xmlns:" + prefix; - - context.setAttributeNS(XMLNamespaceConstants.XMLNS_NS_URI, nsAttrName, nsUri); - } - } - } - } - - /** - * Collect all the namespace URIs used in the subtree of a given element. - * - * @param context The element that should be searched for namespace URIs. - * @return All namespace URIs used in the subtree of <code>context</code>, - * including the ones used in <code>context</code> itself. - */ - public static Set collectNamespaceURIs(Element context) { - Set result = new HashSet(); - - collectNamespaceURIsImpl(context, result); - return result; - } - - /** - * A recursive method to do the work of <code>collectNamespaceURIs</code>. - * - * @param context The context element to evaluate. - * @param result The result, passed as a parameter to avoid unnecessary - * instantiations of <code>Set</code>. - */ - private static void collectNamespaceURIsImpl(Element context, Set result) { - NamedNodeMap attrs = context.getAttributes(); - NodeList childNodes = context.getChildNodes(); - String nsUri; - int i; - - // add the namespace of the context element - nsUri = context.getNamespaceURI(); - if (nsUri != null && nsUri != XMLNamespaceConstants.XMLNS_NS_URI) { - result.add(nsUri); - } - - // add all namespace URIs from attributes - for (i = 0; i < attrs.getLength(); i++) { - nsUri = attrs.item(i).getNamespaceURI(); - if (nsUri != null && nsUri != XMLNamespaceConstants.XMLNS_NS_URI) { - result.add(nsUri); - } - } - - // add all namespaces from subelements - for (i = 0; i < childNodes.getLength(); i++) { - Node node = childNodes.item(i); - - if (node.getNodeType() == Node.ELEMENT_NODE) { - collectNamespaceURIsImpl((Element) node, result); - } - } - } - - /** - * Check, that each attribute node in the given <code>NodeList</code> has its - * parent in the <code>NodeList</code> as well. - * - * @param nodes The <code>NodeList</code> to check. - * @return <code>true</code>, if each attribute node in <code>nodes</code> - * has its parent in <code>nodes</code> as well. - */ - public static boolean checkAttributeParentsInNodeList(NodeList nodes) { - Set nodeSet = new HashSet(); - int i; - - // put the nodes into the nodeSet - for (i = 0; i < nodes.getLength(); i++) { - nodeSet.add(nodes.item(i)); - } - - // check that each attribute node's parent is in the node list - for (i = 0; i < nodes.getLength(); i++) { - Node n = nodes.item(i); - - if (n.getNodeType() == Node.ATTRIBUTE_NODE) { - Attr attr = (Attr) n; - Element owner = attr.getOwnerElement(); - - if (owner == null) { - if (!isNamespaceDeclaration(attr)) { - return false; - } - } - - if (!nodeSet.contains(owner) && !isNamespaceDeclaration(attr)) { - return false; - } - } - } - - return true; - } - - /** - * Convert an unstructured <code>NodeList</code> into a - * <code>DocumentFragment</code>. - * - * @param nodeList Contains the node list to be converted into a DOM - * DocumentFragment. - * @return the resulting DocumentFragment. The DocumentFragment will be - * backed by a new DOM Document, i.e. all noded of the node list will be - * cloned. - * @throws ParserConfigurationException An error occurred creating the - * DocumentFragment. - * @precondition The nodes in the node list appear in document order - * @precondition for each Attr node in the node list, the owning Element is - * in the node list as well. - * @precondition each Element or Attr node in the node list is namespace - * aware. - */ - public static DocumentFragment nodeList2DocumentFragment(NodeList nodeList) - throws ParserConfigurationException { - - DocumentBuilder builder = - DocumentBuilderFactory.newInstance().newDocumentBuilder(); - Document doc = builder.newDocument(); - DocumentFragment result = doc.createDocumentFragment(); - - if (null == nodeList || nodeList.getLength() == 0) { - return result; - } - - int currPos = 0; - currPos = - nodeList2DocumentFragment(nodeList, currPos, result, null, null) + 1; - - while (currPos < nodeList.getLength()) { - currPos = - nodeList2DocumentFragment(nodeList, currPos, result, null, null) + 1; - } - return result; - } - - /** - * Helper method for the <code>nodeList2DocumentFragment</code>. - * - * @param nodeList The <code>NodeList</code> to convert. - * @param currPos The current position in the <code>nodeList</code>. - * @param result The resulting <code>DocumentFragment</code>. - * @param currOrgElem The current original element. - * @param currClonedElem The current cloned element. - * @return The current position. - */ - private static int nodeList2DocumentFragment( - NodeList nodeList, - int currPos, - DocumentFragment result, - Element currOrgElem, - Element currClonedElem) { - - while (currPos < nodeList.getLength()) { - Node currentNode = nodeList.item(currPos); - switch (currentNode.getNodeType()) { - case Node.COMMENT_NODE : - case Node.PROCESSING_INSTRUCTION_NODE : - case Node.TEXT_NODE : - { - // Append current node either to resulting DocumentFragment or to - // current cloned Element - if (null == currClonedElem) { - result.appendChild( - result.getOwnerDocument().importNode(currentNode, false)); - } else { - // Stop processing if current Node is not a descendant of - // current Element - if (!isAncestor(currOrgElem, currentNode)) { - return --currPos; - } - - currClonedElem.appendChild( - result.getOwnerDocument().importNode(currentNode, false)); - } - break; - } - - case Node.ELEMENT_NODE : - { - Element nextCurrOrgElem = (Element) currentNode; - Element nextCurrClonedElem = - result.getOwnerDocument().createElementNS( - nextCurrOrgElem.getNamespaceURI(), - nextCurrOrgElem.getNodeName()); - - // Append current Node either to resulting DocumentFragment or to - // current cloned Element - if (null == currClonedElem) { - result.appendChild(nextCurrClonedElem); - currOrgElem = nextCurrOrgElem; - currClonedElem = nextCurrClonedElem; - } else { - // Stop processing if current Node is not a descendant of - // current Element - if (!isAncestor(currOrgElem, currentNode)) { - return --currPos; - } - - currClonedElem.appendChild(nextCurrClonedElem); - } - - // Process current Node (of type Element) recursively - currPos = - nodeList2DocumentFragment( - nodeList, - ++currPos, - result, - nextCurrOrgElem, - nextCurrClonedElem); - - break; - } - - case Node.ATTRIBUTE_NODE : - { - Attr currAttr = (Attr) currentNode; - - // GK 20030411: Hack to overcome problems with IAIK IXSIL - if (currAttr.getOwnerElement() == null) - break; - if (currClonedElem == null) - break; - - // currClonedElem must be the owner Element of currAttr if - // preconditions are met - currClonedElem.setAttributeNS( - currAttr.getNamespaceURI(), - currAttr.getNodeName(), - currAttr.getValue()); - break; - } - - default : - { - // All other nodes will be ignored - } - } - - currPos++; - } - - return currPos; - } - - /** - * Check, if the given attribute is a namespace declaration. - * - * @param attr The attribute to check. - * @return <code>true</code>, if the attribute is a namespace declaration, - * <code>false</code> otherwise. - */ - private static boolean isNamespaceDeclaration(Attr attr) { - return XMLNamespaceConstants.XMLNS_NS_URI.equals(attr.getNamespaceURI()); - } - - /** - * Check, if a given DOM element is an ancestor of a given node. - * - * @param candAnc The DOM element to check for being the ancestor. - * @param cand The node to check for being the child. - * @return <code>true</code>, if <code>candAnc</code> is an (indirect) - * ancestor of <code>cand</code>; <code>false</code> otherwise. - */ - public static boolean isAncestor(Element candAnc, Node cand) { - Node currPar = cand.getParentNode(); - - while (currPar != null) { - if (candAnc == currPar) - return true; - currPar = currPar.getParentNode(); - } - return false; - } - - /** - * Selects the (first) element from a node list and returns it. - * - * @param nl The NodeList to get the element from. - * @return The (first) element included in the node list or <code>null</code> - * if the node list is <code>null</code> or empty or no element is - * included in the list. - */ - public static Element getElementFromNodeList (NodeList nl) { - if ((nl == null) || (nl.getLength() == 0)) { - return null; - } - for (int i=0; i<nl.getLength(); i++) { - Node node = nl.item(i); - if (node.getNodeType() == Node.ELEMENT_NODE) { - return (Element)node; - } - } - return null; - } - - /** - * Returns all child elements of the given element. - * - * @param parent The element to get the child elements from. - * - * @return A list including all child elements of the given element. - * Maybe empty if the parent element has no child elements. - */ - public static List getChildElements (Element parent) { - Vector v = new Vector(); - NodeList nl = parent.getChildNodes(); - int length = nl.getLength(); - for (int i=0; i < length; i++) { - Node node = nl.item(i); - if (node.getNodeType() == Node.ELEMENT_NODE) { - v.add((Element)node); - } - } - return v; - } - - /** - * Returns a byte array from given node. - * @param node - * @return - * @throws TransformerException - */ - public static byte[] nodeToByteArray(Node node) throws TransformerException { - Source source = new DOMSource(node); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - //StringWriter stringWriter = new StringWriter(); - Result result = new StreamResult(out); - TransformerFactory factory = TransformerFactory.newInstance(); - Transformer transformer = factory.newTransformer(); - transformer.transform(source, result); - return out.toByteArray(); - } - - -} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DomUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DomUtils.java new file mode 100644 index 00000000..818523d0 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DomUtils.java @@ -0,0 +1,1158 @@ +/* + * 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.utils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Vector; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.parsers.SAXParser; +import org.apache.xerces.parsers.XMLGrammarPreparser; +import org.apache.xerces.util.SymbolTable; +import org.apache.xerces.util.XMLGrammarPoolImpl; +import org.apache.xerces.xni.grammars.XMLGrammarDescription; +import org.apache.xerces.xni.grammars.XMLGrammarPool; +import org.apache.xerces.xni.parser.XMLInputSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * Various utility functions for handling XML DOM trees. + * + *<p> + * The parsing methods in this class make use of some features internal to the Xerces DOM parser, + * mainly for performance reasons. As soon as JAXP (currently at version 1.2) is better at schema + * handling, it should be used as the parser interface. + *</p> + * + */ +public class DomUtils { + private static final Logger log = LoggerFactory.getLogger(DomUtils.class); + + /** Feature URI for namespace aware parsing. */ + private static final String NAMESPACES_FEATURE = "http://xml.org/sax/features/namespaces"; + /** Feature URI for validating parsing. */ + private static final String VALIDATION_FEATURE = "http://xml.org/sax/features/validation"; + /** Feature URI for schema validating parsing. */ + private static final String SCHEMA_VALIDATION_FEATURE = + "http://apache.org/xml/features/validation/schema"; + /** Feature URI for normalization of element/attribute values. */ + private static final String NORMALIZED_VALUE_FEATURE = + "http://apache.org/xml/features/validation/schema/normalized-value"; + /** Feature URI for parsing ignorable whitespace. */ + private static final String INCLUDE_IGNORABLE_WHITESPACE_FEATURE = + "http://apache.org/xml/features/dom/include-ignorable-whitespace"; + /** Feature URI for creating EntityReference nodes in the DOM tree. */ + private static final String CREATE_ENTITY_REF_NODES_FEATURE = + "http://apache.org/xml/features/dom/create-entity-ref-nodes"; + /** Property URI for providing external schema locations. */ + private static final String EXTERNAL_SCHEMA_LOCATION_PROPERTY = + "http://apache.org/xml/properties/schema/external-schemaLocation"; + /** + * Property URI for providing the external schema location for elements without a namespace. + */ + private static final String EXTERNAL_NO_NAMESPACE_SCHEMA_LOCATION_PROPERTY = + "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"; + + private static final String EXTERNAL_GENERAL_ENTITIES_FEATURE = + "http://xml.org/sax/features/external-general-entities"; + + private static final String EXTERNAL_PARAMETER_ENTITIES_FEATURE = + "http://xml.org/sax/features/external-parameter-entities"; + + public static final String DISALLOW_DOCTYPE_FEATURE = + "http://apache.org/xml/features/disallow-doctype-decl"; + + + + /** Property URI for the Xerces grammar pool. */ + private static final String GRAMMAR_POOL = org.apache.xerces.impl.Constants.XERCES_PROPERTY_PREFIX + + org.apache.xerces.impl.Constants.XMLGRAMMAR_POOL_PROPERTY; + /** A prime number for initializing the symbol table. */ + private static final int BIG_PRIME = 2039; + /** Symbol table for the grammar pool. */ + private static SymbolTable symbolTable = new SymbolTable(BIG_PRIME); + /** Xerces schema grammar pool. */ + private static XMLGrammarPool grammarPool = new XMLGrammarPoolImpl(); + /** + * Set holding the NamespaceURIs of the grammarPool, to prevent multiple entries of same grammars + * to the pool. + */ + private static Set grammarNamespaces; + + static { + grammarPool.lockPool(); + grammarNamespaces = new HashSet(); + } + + /** + * Preparse a schema and add it to the schema pool. The method only adds the schema to the pool if + * a schema having the same <code>systemId</code> (namespace URI) is not already present in the + * pool. + * + * @param inputStream An <code>InputStream</code> providing the contents of the schema. + * @param systemId The systemId (namespace URI) to use for the schema. + * @throws IOException An error occurred reading the schema. + */ + public static void addSchemaToPool(final InputStream inputStream, final String systemId) + throws IOException { + XMLGrammarPreparser preparser; + + if (!grammarNamespaces.contains(systemId)) { + + grammarNamespaces.add(systemId); + + // unlock the pool so that we can add another grammar + grammarPool.unlockPool(); + + // prepare the preparser + preparser = new XMLGrammarPreparser(symbolTable); + preparser.registerPreparser(XMLGrammarDescription.XML_SCHEMA, null); + preparser.setProperty(GRAMMAR_POOL, grammarPool); + preparser.setFeature(NAMESPACES_FEATURE, true); + preparser.setFeature(VALIDATION_FEATURE, true); + + // add the grammar to the pool + preparser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA, + new XMLInputSource(null, systemId, null, inputStream, null)); + + // lock the pool again so that schemas are not added automatically + grammarPool.lockPool(); + } + } + + /** + * Parse an XML document from an <code>InputStream</code>. + * + *<p> + * It uses a <code>MOAEntityResolver</code> as the <code>EntityResolver</code> and a + * <code>MOAErrorHandler</code> as the <code>ErrorHandler</code>. + *</p> + * + * @param inputStream The <code>InputStream</code> containing the XML document. + * @param validating If <code>true</code>, parse validating. + * @param externalSchemaLocations A <code>String</code> containing namespace URI to schema + * location pairs, the same way it is accepted by the <code>xsi: + * schemaLocation</code> attribute. + * @param externalNoNamespaceSchemaLocation The schema location of the schema for elements without + * a namespace, the same way it is accepted by the + * <code>xsi:noNamespaceSchemaLocation</code> attribute. + * @param parserFeatures Map of features that should be set into XML parser + * @return The parsed XML document as a DOM tree. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document. + * @throws ParserConfigurationException An error occurred configuring the XML parser. + */ + public static Document parseDocument(final InputStream inputStream, final boolean validating, + final String externalSchemaLocations, final String externalNoNamespaceSchemaLocation, + final Map<String, Object> parserFeatures) + throws SAXException, IOException, ParserConfigurationException { + + return parseDocument(inputStream, validating, externalSchemaLocations, + externalNoNamespaceSchemaLocation, new EaafDomEntityResolver(), null, parserFeatures); + } + + /** + * Parse an XML document from a <code>String</code>. + * + *<p> + * It uses a <code>MOAEntityResolver</code> as the <code>EntityResolver</code> and a + * <code>MOAErrorHandler</code> as the <code>ErrorHandler</code>. + *</p> + * + * @param xmlString The <code>String</code> containing the XML document. + * @param encoding The encoding of the XML document. + * @param validating If <code>true</code>, parse validating. + * @param externalSchemaLocations A <code>String</code> containing namespace URI to schema + * location pairs, the same way it is accepted by the <code>xsi: + * schemaLocation</code> attribute. + * @param externalNoNamespaceSchemaLocation The schema location of the schema for elements without + * a namespace, the same way it is accepted by the + * <code>xsi:noNamespaceSchemaLocation</code> attribute. + * @return The parsed XML document as a DOM tree. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document. + * @throws ParserConfigurationException An error occurred configuring the XML parser. + */ + public static Document parseDocument(final String xmlString, final String encoding, + final boolean validating, final String externalSchemaLocations, + final String externalNoNamespaceSchemaLocation, final Map<String, Object> parserFeatures) + throws SAXException, IOException, ParserConfigurationException { + + final InputStream in = new ByteArrayInputStream(xmlString.getBytes(encoding)); + return parseDocument(in, validating, externalSchemaLocations, externalNoNamespaceSchemaLocation, + parserFeatures); + } + + /** + * Parse an XML document from a <code>String</code>. + * + *<p> + * It uses a <code>MOAEntityResolver</code> as the <code>EntityResolver</code> and a + * <code>MOAErrorHandler</code> as the <code>ErrorHandler</code>. + *</p> + * + * @param xmlString The <code>String</code> containing the XML document. + * @param encoding The encoding of the XML document. + * @param validating If <code>true</code>, parse validating. + * @param externalSchemaLocations A <code>String</code> containing namespace URI to schema + * location pairs, the same way it is accepted by the <code>xsi: + * schemaLocation</code> attribute. + * @param externalNoNamespaceSchemaLocation The schema location of the schema for elements without + * a namespace, the same way it is accepted by the + * <code>xsi:noNamespaceSchemaLocation</code> attribute. + * @return The parsed XML document as a DOM tree. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document. + * @throws ParserConfigurationException An error occurred configuring the XML parser. + */ + public static Document parseDocument(final String xmlString, final String encoding, + final boolean validating, final String externalSchemaLocations, + final String externalNoNamespaceSchemaLocation) + throws SAXException, IOException, ParserConfigurationException { + + final InputStream in = new ByteArrayInputStream(xmlString.getBytes(encoding)); + return parseDocument(in, validating, externalSchemaLocations, externalNoNamespaceSchemaLocation, + null); + } + + /** + * Parse an UTF-8 encoded XML document from a <code>String</code>. + * + * @param xmlString The <code>String</code> containing the XML document. + * @param validating If <code>true</code>, parse validating. + * @param externalSchemaLocations A <code>String</code> containing namespace URI to schema + * location pairs, the same way it is accepted by the <code>xsi: + * schemaLocation</code> attribute. + * @param externalNoNamespaceSchemaLocation The schema location of the schema for elements without + * a namespace, the same way it is accepted by the + * <code>xsi:noNamespaceSchemaLocation</code> attribute. + * @return The parsed XML document as a DOM tree. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document. + * @throws ParserConfigurationException An error occurred configuring the XML parser. + */ + public static Document parseDocument(final String xmlString, final boolean validating, + final String externalSchemaLocations, final String externalNoNamespaceSchemaLocation) + throws SAXException, IOException, ParserConfigurationException { + + return parseDocument(xmlString, "UTF-8", validating, externalSchemaLocations, + externalNoNamespaceSchemaLocation); + } + + /** + * Parse an XML document from an <code>InputStream</code>. + * + * @param inputStream The <code>InputStream</code> containing the XML document. + * @param validating If <code>true</code>, parse validating. + * @param externalSchemaLocations A <code>String</code> containing namespace URI to schema + * location pairs, the same way it is accepted by the <code>xsi: + * schemaLocation</code> attribute. + * @param externalNoNamespaceSchemaLocation The schema location of the schema for elements without + * a namespace, the same way it is accepted by the + * <code>xsi:noNamespaceSchemaLocation</code> attribute. + * @param entityResolver An <code>EntityResolver</code> to resolve external entities (schemas and + * DTDs). If <code>null</code>, it will not be set. + * @param errorHandler An <code>ErrorHandler</code> to decide what to do with parsing errors. If + * <code>null</code>, it will not be set. + * @return The parsed XML document as a DOM tree. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document. + * @throws ParserConfigurationException An error occurred configuring the XML parser. + */ + public static Document parseDocument(final InputStream inputStream, final boolean validating, + final String externalSchemaLocations, final String externalNoNamespaceSchemaLocation, + final EntityResolver entityResolver, final ErrorHandler errorHandler, + final Map<String, Object> parserFeatures) + throws SAXException, IOException, ParserConfigurationException { + + DOMParser parser; + + // class MyEntityResolver implements EntityResolver { + // + // public InputSource resolveEntity(String publicId, String systemId) + // throws SAXException, IOException { + // return new InputSource(new ByteArrayInputStream(new byte[0])); + // } + // } + + + // if Debug is enabled make a copy of inputStream to enable debug output in case of SAXException + byte[] buffer = null; + ByteArrayInputStream baStream = null; + if (true == log.isDebugEnabled()) { + buffer = IOUtils.toByteArray(inputStream); + baStream = new ByteArrayInputStream(buffer); + + } + + + + // create the DOM parser + if (symbolTable != null) { + parser = new DOMParser(symbolTable, grammarPool); + } else { + parser = new DOMParser(); + } + + // set parser features and properties + try { + parser.setFeature(NAMESPACES_FEATURE, true); + parser.setFeature(VALIDATION_FEATURE, validating); + parser.setFeature(SCHEMA_VALIDATION_FEATURE, validating); + parser.setFeature(NORMALIZED_VALUE_FEATURE, false); + parser.setFeature(INCLUDE_IGNORABLE_WHITESPACE_FEATURE, true); + parser.setFeature(CREATE_ENTITY_REF_NODES_FEATURE, false); + parser.setFeature(EXTERNAL_GENERAL_ENTITIES_FEATURE, false); + parser.setFeature(EXTERNAL_PARAMETER_ENTITIES_FEATURE, false); + + // set external added parser features + if (parserFeatures != null) { + for (final Entry<String, Object> el : parserFeatures.entrySet()) { + final String key = el.getKey(); + if (StringUtils.isNotEmpty(key)) { + final Object value = el.getValue(); + if (value != null && value instanceof Boolean) { + parser.setFeature(key, (boolean) value); + } else { + log.warn("This XML parser only allows features with 'boolean' values"); + } + + } else { + log.warn("Can not set 'null' feature to XML parser"); + } + } + } + + // fix XXE problem + // parser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + + + if (validating) { + if (externalSchemaLocations != null) { + parser.setProperty(EXTERNAL_SCHEMA_LOCATION_PROPERTY, externalSchemaLocations); + } + if (externalNoNamespaceSchemaLocation != null) { + parser.setProperty(EXTERNAL_NO_NAMESPACE_SCHEMA_LOCATION_PROPERTY, + externalNoNamespaceSchemaLocation); + } + } + + // set entity resolver and error handler + if (entityResolver != null) { + parser.setEntityResolver(entityResolver); + } + if (errorHandler != null) { + parser.setErrorHandler(errorHandler); + } + + // parse the document and return it + // if debug is enabled: use copy of strem (baStream) else use orig stream + if (null != baStream) { + parser.parse(new InputSource(baStream)); + } else { + parser.parse(new InputSource(inputStream)); + } + } catch (final SAXException e) { + if (true == log.isDebugEnabled() && null != buffer) { + final String xmlContent = new String(buffer, "UTF-8"); + log.debug("SAXException in:\n" + xmlContent); + } + throw (e); + } + + return parser.getDocument(); + } + + /** + * Simple document parser. + * + * @param inputStream data to parse + * @return Element + * @throws SAXException In case of an error + * @throws IOException In case of an error + * @throws ParserConfigurationException In case of an error + */ + public static Document parseDocumentSimple(final InputStream inputStream) + throws SAXException, IOException, ParserConfigurationException { + + DOMParser parser; + + parser = new DOMParser(); + // set parser features and properties + parser.setFeature(NAMESPACES_FEATURE, true); + parser.setFeature(VALIDATION_FEATURE, false); + parser.setFeature(SCHEMA_VALIDATION_FEATURE, false); + parser.setFeature(NORMALIZED_VALUE_FEATURE, false); + parser.setFeature(INCLUDE_IGNORABLE_WHITESPACE_FEATURE, true); + parser.setFeature(CREATE_ENTITY_REF_NODES_FEATURE, false); + + parser.parse(new InputSource(inputStream)); + + return parser.getDocument(); + } + + + + + + + + + + + + /** + * A convenience method to parse an XML document validating. + * + * @param inputStream The <code>InputStream</code> containing the XML document. + * @return The root element of the parsed XML document. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document. + * @throws ParserConfigurationException An error occurred configuring the XML parser. + */ + public static Element parseXmlValidating(final InputStream inputStream) + throws ParserConfigurationException, SAXException, IOException { + return DomUtils + .parseDocument(inputStream, true, XMLNamespaceConstants.ALL_SCHEMA_LOCATIONS, null, null) + .getDocumentElement(); + } + + /** + * A convenience method to parse an XML document validating. + * + * @param inputStream The <code>InputStream</code> containing the XML document. + * @param parserFeatures Set additional features to XML parser + * @return The root element of the parsed XML document. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document. + * @throws ParserConfigurationException An error occurred configuring the XML parser. + */ + public static Element parseXmlValidating(final InputStream inputStream, + final Map<String, Object> parserFeatures) + throws ParserConfigurationException, SAXException, IOException { + return DomUtils.parseDocument(inputStream, true, XMLNamespaceConstants.ALL_SCHEMA_LOCATIONS, + null, parserFeatures).getDocumentElement(); + } + + /** + * A convenience method to parse an XML document non validating. This method disallow DocType + * declarations + * + * @param inputStream The <code>InputStream</code> containing the XML document. + * @return The root element of the parsed XML document. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document. + * @throws ParserConfigurationException An error occurred configuring the XML parser. + */ + public static Element parseXmlNonValidating(final InputStream inputStream) + throws ParserConfigurationException, SAXException, IOException { + return DomUtils.parseDocument(inputStream, false, XMLNamespaceConstants.ALL_SCHEMA_LOCATIONS, + null, Collections.unmodifiableMap(new HashMap<String, Object>() { + private static final long serialVersionUID = 1L; + { + put(DomUtils.DISALLOW_DOCTYPE_FEATURE, true); + + } + })).getDocumentElement(); + } + + /** + * Schema validate a given DOM element. + * + * @param element The element to validate. + * @param externalSchemaLocations A <code>String</code> containing namespace URI to schema + * location pairs, the same way it is accepted by the <code>xsi: + * schemaLocation</code> attribute. + * @param externalNoNamespaceSchemaLocation The schema location of the schema for elements without + * a namespace, the same way it is accepted by the + * <code>xsi:noNamespaceSchemaLocation</code> attribute. + * @return <code>true</code>, if the <code>element</code> validates against the schemas declared + * in it. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document from its serialized representation. + * @throws ParserConfigurationException An error occurred configuring the XML + * @throws TransformerException An error occurred serializing the element. + */ + public static boolean validateElement(final Element element, final String externalSchemaLocations, + final String externalNoNamespaceSchemaLocation) + throws ParserConfigurationException, IOException, SAXException, TransformerException { + + byte[] docBytes; + SAXParser parser; + + // create the SAX parser + if (symbolTable != null) { + parser = new SAXParser(symbolTable, grammarPool); + } else { + parser = new SAXParser(); + } + + // serialize the document + docBytes = serializeNode(element, "UTF-8"); + + // set up parser features and attributes + parser.setFeature(NAMESPACES_FEATURE, true); + parser.setFeature(VALIDATION_FEATURE, true); + parser.setFeature(SCHEMA_VALIDATION_FEATURE, true); + parser.setFeature(EXTERNAL_GENERAL_ENTITIES_FEATURE, false); + parser.setFeature(DISALLOW_DOCTYPE_FEATURE, true); + + + if (externalSchemaLocations != null) { + parser.setProperty(EXTERNAL_SCHEMA_LOCATION_PROPERTY, externalSchemaLocations); + } + if (externalNoNamespaceSchemaLocation != null) { + parser.setProperty(EXTERNAL_NO_NAMESPACE_SCHEMA_LOCATION_PROPERTY, + "externalNoNamespaceSchemaLocation"); + } + + // set up entity resolver and error handler + parser.setEntityResolver(new EaafDomEntityResolver()); + + // parse validating + parser.parse(new InputSource(new ByteArrayInputStream(docBytes))); + return true; + } + + + /** + * Schema validate a given DOM element. + * + * @param element The element to validate. + * @param externalSchemaLocations A <code>String</code> containing namespace URI to schema + * location pairs, the same way it is accepted by the <code>xsi: + * schemaLocation</code> attribute. + * @param externalNoNamespaceSchemaLocation The schema location of the schema for elements without + * a namespace, the same way it is accepted by the + * <code>xsi:noNamespaceSchemaLocation</code> attribute. + * @return <code>true</code>, if the <code>element</code> validates against the schemas declared + * in it. + * @throws SAXException An error occurred parsing the document. + * @throws IOException An error occurred reading the document from its serialized representation. + * @throws ParserConfigurationException An error occurred configuring the XML + * @throws TransformerException An error occurred serializing the element. + */ + public static boolean validateElement(final Element element, final String externalSchemaLocations, + final String externalNoNamespaceSchemaLocation, final EntityResolver entityResolver) + throws ParserConfigurationException, IOException, SAXException, TransformerException { + + byte[] docBytes; + SAXParser parser; + + // create the SAX parser + if (symbolTable != null) { + parser = new SAXParser(symbolTable, grammarPool); + } else { + parser = new SAXParser(); + } + + // serialize the document + docBytes = serializeNode(element, "UTF-8"); + + // set up parser features and attributes + parser.setFeature(NAMESPACES_FEATURE, true); + parser.setFeature(VALIDATION_FEATURE, true); + parser.setFeature(SCHEMA_VALIDATION_FEATURE, true); + + if (externalSchemaLocations != null) { + parser.setProperty(EXTERNAL_SCHEMA_LOCATION_PROPERTY, externalSchemaLocations); + } + if (externalNoNamespaceSchemaLocation != null) { + parser.setProperty(EXTERNAL_NO_NAMESPACE_SCHEMA_LOCATION_PROPERTY, + "externalNoNamespaceSchemaLocation"); + } + + // set up entity resolver and error handler + parser.setEntityResolver(entityResolver); + + // parse validating + parser.parse(new InputSource(new ByteArrayInputStream(docBytes))); + return true; + } + + /** + * Serialize the given DOM node. + * + *<p> + * The node will be serialized using the UTF-8 encoding. + *</p> + * + * @param node The node to serialize. + * @return String The <code>String</code> representation of the given DOM node. + * @throws TransformerException An error occurred transforming the node to a <code>String</code>. + * @throws IOException An IO error occurred writing the node to a byte array. + */ + public static String serializeNode(final Node node) throws TransformerException, IOException { + return new String(serializeNode(node, "UTF-8", false), "UTF-8"); + } + + + /** + * Serialize the given DOM node. + * + *<p> + * The node will be serialized using the UTF-8 encoding. + *</p> + * + * @param node The node to serialize. + * @param omitXmlDeclaration The boolean value for omitting the XML Declaration. + * @return String The <code>String</code> representation of the given DOM node. + * @throws TransformerException An error occurred transforming the node to a <code>String</code>. + * @throws IOException An IO error occurred writing the node to a byte array. + */ + public static String serializeNode(final Node node, final boolean omitXmlDeclaration) + throws TransformerException, IOException { + return new String(serializeNode(node, "UTF-8", omitXmlDeclaration), "UTF-8"); + } + + /** + * Serialize the given DOM node. + * + *<p> + * The node will be serialized using the UTF-8 encoding. + *</p> + * + * @param node The node to serialize. + * @param omitXmlDeclaration The boolean value for omitting the XML Declaration. + * @param lineSeperator Sets the line seperator String of the parser + * @return String The <code>String</code> representation of the given DOM node. + * @throws TransformerException An error occurred transforming the node to a <code>String</code>. + * @throws IOException An IO error occurred writing the node to a byte array. + */ + public static String serializeNode(final Node node, final boolean omitXmlDeclaration, + final String lineSeperator) throws TransformerException, IOException { + return new String(serializeNode(node, "UTF-8", omitXmlDeclaration, lineSeperator), "UTF-8"); + } + + /** + * Serialize the given DOM node to a byte array. + * + * @param node The node to serialize. + * @param xmlEncoding The XML encoding to use. + * @return The serialized node, as a byte array. Using a compatible encoding this can easily be + * converted into a <code>String</code>. + * @throws TransformerException An error occurred transforming the node to a byte array. + * @throws IOException An IO error occurred writing the node to a byte array. + */ + public static byte[] serializeNode(final Node node, final String xmlEncoding) + throws TransformerException, IOException { + return serializeNode(node, xmlEncoding, false); + } + + /** + * Serialize the given DOM node to a byte array. + * + * @param node The node to serialize. + * @param xmlEncoding The XML encoding to use. + * @param omitDeclaration The boolean value for omitting the XML Declaration. + * @return The serialized node, as a byte array. Using a compatible encoding this can easily be + * converted into a <code>String</code>. + * @throws TransformerException An error occurred transforming the node to a byte array. + * @throws IOException An IO error occurred writing the node to a byte array. + */ + public static byte[] serializeNode(final Node node, final String xmlEncoding, + final boolean omitDeclaration) throws TransformerException, IOException { + return serializeNode(node, xmlEncoding, omitDeclaration, null); + } + + + /** + * Serialize the given DOM node to a byte array. + * + * @param node The node to serialize. + * @param xmlEncoding The XML encoding to use. + * @param omitDeclaration The boolean value for omitting the XML Declaration. + * @param lineSeperator Sets the line seperator String of the parser + * @return The serialized node, as a byte array. Using a compatible encoding this can easily be + * converted into a <code>String</code>. + * @throws TransformerException An error occurred transforming the node to a byte array. + * @throws IOException An IO error occurred writing the node to a byte array. + */ + public static byte[] serializeNode(final Node node, final String xmlEncoding, + final boolean omitDeclaration, final String lineSeperator) + throws TransformerException, IOException { + + final TransformerFactory transformerFactory = TransformerFactory.newInstance(); + final Transformer transformer = transformerFactory.newTransformer(); + final ByteArrayOutputStream bos = new ByteArrayOutputStream(16384); + + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.ENCODING, xmlEncoding); + final String omit = omitDeclaration ? "yes" : "no"; + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, omit); + if (null != lineSeperator) { + transformer.setOutputProperty("{http://xml.apache.org/xalan}line-separator", lineSeperator); + // does not work for xalan <= 2.5.1 + } + transformer.transform(new DOMSource(node), new StreamResult(bos)); + + bos.flush(); + bos.close(); + + return bos.toByteArray(); + } + + /** + * Return the text that a node contains. + * + *<p> + * This routine: + * </p> + * <ul> + * <li>Ignores comments and processing instructions.</li> + * <li>Concatenates TEXT nodes, CDATA nodes, and the results recursively processing EntityRef + * nodes.</li> + * <li>Ignores any element nodes in the sublist. (Other possible options are to recurse into + * element sublists or throw an exception.)</li> + * </ul> + * + * @param node A DOM node from which to extract text. + * @return A String representing its contents. + */ + public static String getText(final Node node) { + if (!node.hasChildNodes()) { + return ""; + } + + final StringBuffer result = new StringBuffer(); + final NodeList list = node.getChildNodes(); + + for (int i = 0; i < list.getLength(); i++) { + final Node subnode = list.item(i); + if (subnode.getNodeType() == Node.TEXT_NODE) { + result.append(subnode.getNodeValue()); + } else if (subnode.getNodeType() == Node.CDATA_SECTION_NODE) { + result.append(subnode.getNodeValue()); + } else if (subnode.getNodeType() == Node.ENTITY_REFERENCE_NODE) { + // Recurse into the subtree for text + // (and ignore comments) + result.append(getText(subnode)); + } + } + return result.toString(); + } + + /** + * Build the namespace prefix to namespace URL mapping in effect for a given node. + * + * @param node The context node for which build the map. + * @return The namespace prefix to namespace URL mapping ( a <code>String</code> value to + * <code>String</code> value mapping). + */ + public static Map getNamespaceDeclarations(Node node) { + final Map nsDecls = new HashMap(); + int i; + + do { + if (node.hasAttributes()) { + final NamedNodeMap attrs = node.getAttributes(); + + for (i = 0; i < attrs.getLength(); i++) { + final Attr attr = (Attr) attrs.item(i); + + // add prefix mapping if none exists + if ("xmlns".equals(attr.getPrefix()) || "xmlns".equals(attr.getName())) { + + final String nsPrefix = attr.getPrefix() != null ? attr.getLocalName() : ""; + + if (nsDecls.get(nsPrefix) == null) { + nsDecls.put(nsPrefix, attr.getValue()); + } + } + } + } + } while ((node = node.getParentNode()) != null); + + return nsDecls; + } + + /** + * Add all namespace declarations declared in the parent(s) of a given element and used in the + * subtree of the given element to the given element. + * + * @param context The element to which to add the namespaces. + */ + public static void localizeNamespaceDeclarations(final Element context) { + final Node parent = context.getParentNode(); + + if (parent != null) { + final Map namespaces = getNamespaceDeclarations(context.getParentNode()); + final Set nsUris = collectNamespaceUris(context); + Iterator iter; + + for (iter = namespaces.entrySet().iterator(); iter.hasNext();) { + final Map.Entry e = (Map.Entry) iter.next(); + + if (nsUris.contains(e.getValue())) { + final String prefix = (String) e.getKey(); + final String nsUri = (String) e.getValue(); + final String nsAttrName = "".equals(prefix) ? "xmlns" : "xmlns:" + prefix; + + context.setAttributeNS(XMLNamespaceConstants.XMLNS_NS_URI, nsAttrName, nsUri); + } + } + } + } + + /** + * Collect all the namespace URIs used in the subtree of a given element. + * + * @param context The element that should be searched for namespace URIs. + * @return All namespace URIs used in the subtree of <code>context</code>, including the ones used + * in <code>context</code> itself. + */ + public static Set collectNamespaceUris(final Element context) { + final Set result = new HashSet(); + + collectNamespaceUrisImpl(context, result); + return result; + } + + /** + * A recursive method to do the work of <code>collectNamespaceURIs</code>. + * + * @param context The context element to evaluate. + * @param result The result, passed as a parameter to avoid unnecessary instantiations of + * <code>Set</code>. + */ + private static void collectNamespaceUrisImpl(final Element context, final Set result) { + final NamedNodeMap attrs = context.getAttributes(); + final NodeList childNodes = context.getChildNodes(); + String nsUri; + int i; + + // add the namespace of the context element + nsUri = context.getNamespaceURI(); + if (nsUri != null && nsUri != XMLNamespaceConstants.XMLNS_NS_URI) { + result.add(nsUri); + } + + // add all namespace URIs from attributes + for (i = 0; i < attrs.getLength(); i++) { + nsUri = attrs.item(i).getNamespaceURI(); + if (nsUri != null && nsUri != XMLNamespaceConstants.XMLNS_NS_URI) { + result.add(nsUri); + } + } + + // add all namespaces from subelements + for (i = 0; i < childNodes.getLength(); i++) { + final Node node = childNodes.item(i); + + if (node.getNodeType() == Node.ELEMENT_NODE) { + collectNamespaceUrisImpl((Element) node, result); + } + } + } + + /** + * Check, that each attribute node in the given <code>NodeList</code> has its parent in the + * <code>NodeList</code> as well. + * + * @param nodes The <code>NodeList</code> to check. + * @return <code>true</code>, if each attribute node in <code>nodes</code> has its parent in + * <code>nodes</code> as well. + */ + public static boolean checkAttributeParentsInNodeList(final NodeList nodes) { + final Set nodeSet = new HashSet(); + int i; + + // put the nodes into the nodeSet + for (i = 0; i < nodes.getLength(); i++) { + nodeSet.add(nodes.item(i)); + } + + // check that each attribute node's parent is in the node list + for (i = 0; i < nodes.getLength(); i++) { + final Node n = nodes.item(i); + + if (n.getNodeType() == Node.ATTRIBUTE_NODE) { + final Attr attr = (Attr) n; + final Element owner = attr.getOwnerElement(); + + if (owner == null) { + if (!isNamespaceDeclaration(attr)) { + return false; + } + } + + if (!nodeSet.contains(owner) && !isNamespaceDeclaration(attr)) { + return false; + } + } + } + + return true; + } + + /** + * Convert an unstructured <code>NodeList</code> into a <code>DocumentFragment</code>. + * + * @param nodeList Contains the node list to be converted into a DOM DocumentFragment. + * @return the resulting DocumentFragment. The DocumentFragment will be backed by a new DOM + * Document, i.e. all noded of the node list will be cloned. + * @throws ParserConfigurationException An error occurred creating the DocumentFragment. + * @precondition The nodes in the node list appear in document order + * @precondition for each Attr node in the node list, the owning Element is in the node list as + * well. + * @precondition each Element or Attr node in the node list is namespace aware. + */ + public static DocumentFragment nodeList2DocumentFragment(final NodeList nodeList) + throws ParserConfigurationException { + + final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + final Document doc = builder.newDocument(); + final DocumentFragment result = doc.createDocumentFragment(); + + if (null == nodeList || nodeList.getLength() == 0) { + return result; + } + + int currPos = 0; + currPos = nodeList2DocumentFragment(nodeList, currPos, result, null, null) + 1; + + while (currPos < nodeList.getLength()) { + currPos = nodeList2DocumentFragment(nodeList, currPos, result, null, null) + 1; + } + return result; + } + + /** + * Helper method for the <code>nodeList2DocumentFragment</code>. + * + * @param nodeList The <code>NodeList</code> to convert. + * @param currPos The current position in the <code>nodeList</code>. + * @param result The resulting <code>DocumentFragment</code>. + * @param currOrgElem The current original element. + * @param currClonedElem The current cloned element. + * @return The current position. + */ + private static int nodeList2DocumentFragment(final NodeList nodeList, int currPos, + final DocumentFragment result, Element currOrgElem, Element currClonedElem) { + + while (currPos < nodeList.getLength()) { + final Node currentNode = nodeList.item(currPos); + switch (currentNode.getNodeType()) { + case Node.COMMENT_NODE: + case Node.PROCESSING_INSTRUCTION_NODE: + case Node.TEXT_NODE: { + // Append current node either to resulting DocumentFragment or to + // current cloned Element + if (null == currClonedElem) { + result.appendChild(result.getOwnerDocument().importNode(currentNode, false)); + } else { + // Stop processing if current Node is not a descendant of + // current Element + if (!isAncestor(currOrgElem, currentNode)) { + return --currPos; + } + + currClonedElem.appendChild(result.getOwnerDocument().importNode(currentNode, false)); + } + break; + } + + case Node.ELEMENT_NODE: { + final Element nextCurrOrgElem = (Element) currentNode; + final Element nextCurrClonedElem = result.getOwnerDocument() + .createElementNS(nextCurrOrgElem.getNamespaceURI(), nextCurrOrgElem.getNodeName()); + + // Append current Node either to resulting DocumentFragment or to + // current cloned Element + if (null == currClonedElem) { + result.appendChild(nextCurrClonedElem); + currOrgElem = nextCurrOrgElem; + currClonedElem = nextCurrClonedElem; + } else { + // Stop processing if current Node is not a descendant of + // current Element + if (!isAncestor(currOrgElem, currentNode)) { + return --currPos; + } + + currClonedElem.appendChild(nextCurrClonedElem); + } + + // Process current Node (of type Element) recursively + currPos = nodeList2DocumentFragment(nodeList, ++currPos, result, nextCurrOrgElem, + nextCurrClonedElem); + + break; + } + + case Node.ATTRIBUTE_NODE: { + final Attr currAttr = (Attr) currentNode; + + // GK 20030411: Hack to overcome problems with IAIK IXSIL + if (currAttr.getOwnerElement() == null) { + break; + } + if (currClonedElem == null) { + break; + } + + // currClonedElem must be the owner Element of currAttr if + // preconditions are met + currClonedElem.setAttributeNS(currAttr.getNamespaceURI(), currAttr.getNodeName(), + currAttr.getValue()); + break; + } + + default: { + // All other nodes will be ignored + } + } + + currPos++; + } + + return currPos; + } + + /** + * Check, if the given attribute is a namespace declaration. + * + * @param attr The attribute to check. + * @return <code>true</code>, if the attribute is a namespace declaration, <code>false</code> + * otherwise. + */ + private static boolean isNamespaceDeclaration(final Attr attr) { + return XMLNamespaceConstants.XMLNS_NS_URI.equals(attr.getNamespaceURI()); + } + + /** + * Check, if a given DOM element is an ancestor of a given node. + * + * @param candAnc The DOM element to check for being the ancestor. + * @param cand The node to check for being the child. + * @return <code>true</code>, if <code>candAnc</code> is an (indirect) ancestor of + * <code>cand</code>; <code>false</code> otherwise. + */ + public static boolean isAncestor(final Element candAnc, final Node cand) { + Node currPar = cand.getParentNode(); + + while (currPar != null) { + if (candAnc == currPar) { + return true; + } + currPar = currPar.getParentNode(); + } + return false; + } + + /** + * Selects the (first) element from a node list and returns it. + * + * @param nl The NodeList to get the element from. + * @return The (first) element included in the node list or <code>null</code> if the node list is + * <code>null</code> or empty or no element is included in the list. + */ + public static Element getElementFromNodeList(final NodeList nl) { + if ((nl == null) || (nl.getLength() == 0)) { + return null; + } + for (int i = 0; i < nl.getLength(); i++) { + final Node node = nl.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + return (Element) node; + } + } + return null; + } + + /** + * Returns all child elements of the given element. + * + * @param parent The element to get the child elements from. + * + * @return A list including all child elements of the given element. Maybe empty if the parent + * element has no child elements. + */ + public static List getChildElements(final Element parent) { + final Vector v = new Vector(); + final NodeList nl = parent.getChildNodes(); + final int length = nl.getLength(); + for (int i = 0; i < length; i++) { + final Node node = nl.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + v.add(node); + } + } + return v; + } + + /** + * Returns a byte array from given node. + * + * @param node Element node + * @return transformed node + * @throws TransformerException in case of an error + */ + public static byte[] nodeToByteArray(final Node node) throws TransformerException { + final Source source = new DOMSource(node); + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + // StringWriter stringWriter = new StringWriter(); + final Result result = new StreamResult(out); + final TransformerFactory factory = TransformerFactory.newInstance(); + final Transformer transformer = factory.newTransformer(); + transformer.transform(source, result); + return out.toByteArray(); + } + + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/EAAFDomEntityResolver.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/EAAFDomEntityResolver.java deleted file mode 100644 index 5be0a475..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/EAAFDomEntityResolver.java +++ /dev/null @@ -1,128 +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.utils; - -import java.io.InputStream; - -import org.apache.xerces.util.URI; -import org.apache.xerces.util.URI.MalformedURIException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; - -import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants; - -/** - * An <code>EntityResolver</code> that looks up entities stored as - * local resources. - * - * <p>The following DTDs are mapped to local resources: - * <ul> - * <li>The XMLSchema.dtd</li> - * <li>The datatypes.dtd</li> - * </ul> - * </p> - * <p>For all other resources, an attempt is made to resolve them as resources, - * either absolute or relative to <code>Constants.SCHEMA_ROOT</code>. - * - */ -public class EAAFDomEntityResolver implements EntityResolver { - private static final Logger log = LoggerFactory.getLogger(EAAFDomEntityResolver.class); - - /** - * Resolve an entity. - * - * The <code>systemId</code> parameter is used to perform the lookup of the - * entity as a resource, either by interpreting the <code>systemId</code> as - * an absolute resource path, or by appending the last path component of - * <code>systemId</code> to <code>Constants.SCHEMA_ROOT</code>. - * - * @param publicId The public ID of the resource. - * @param systemId The system ID of the resource. - * @return An <code>InputSource</code> from which the entity can be read, or - * <code>null</code>, if the entity could not be found. - * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, java.lang.String) - */ - public InputSource resolveEntity(String publicId, String systemId) { - InputStream stream; - int slashPos; - - if (publicId != null) { - // check if we can resolve some standard dtd's - if (publicId.equalsIgnoreCase("-//W3C//DTD XMLSchema 200102//EN")) { - return new InputSource( - getClass().getResourceAsStream( - XMLNamespaceConstants.SCHEMA_ROOT + "XMLSchema.dtd")); - } else if (publicId.equalsIgnoreCase("datatypes")) { - return new InputSource( - getClass().getResourceAsStream( - XMLNamespaceConstants.SCHEMA_ROOT + "datatypes.dtd")); - } - } else if (systemId != null) { - // get the URI path - try { - URI uri = new URI(systemId); - systemId = uri.getPath(); - - if (!"file".equals(uri.getScheme()) || "".equals(systemId.trim())) { - return null; - } - - } catch (MalformedURIException e) { - return null; - } - - // try to get the resource from the full path - stream = getClass().getResourceAsStream(systemId); - if (stream != null) { - InputSource source = new InputSource(stream); - - source.setSystemId(systemId); - return source; - } - - // try to get the resource from the last path component - slashPos = systemId.lastIndexOf('/'); - if (slashPos >= 0 && systemId.length() > slashPos) { - systemId = systemId.substring(slashPos + 1, systemId.length()); - stream = - getClass().getResourceAsStream(XMLNamespaceConstants.SCHEMA_ROOT + systemId); - if (stream != null) { - InputSource source = new InputSource(stream); - - source.setSystemId(systemId); - return source; - } - } - } - - return null; // nothing found - let the parser handle the entity - } -}
\ No newline at end of file diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/EaafDomEntityResolver.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/EaafDomEntityResolver.java new file mode 100644 index 00000000..c2700214 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/EaafDomEntityResolver.java @@ -0,0 +1,118 @@ +/* + * 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.utils; + +import java.io.InputStream; +import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants; +import org.apache.xerces.util.URI; +import org.apache.xerces.util.URI.MalformedURIException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; + +/** + * An <code>EntityResolver</code> that looks up entities stored as local resources. + * + * <p> + * The following DTDs are mapped to local resources: + * <ul> + * <li>The XMLSchema.dtd</li> + * <li>The datatypes.dtd</li> + * </ul> + * </p> + * </p> + * For all other resources, an attempt is made to resolve them as resources, either absolute or + * relative to <code>Constants.SCHEMA_ROOT</code>. + * + */ +public class EaafDomEntityResolver implements EntityResolver { + private static final Logger log = LoggerFactory.getLogger(EaafDomEntityResolver.class); + + /** + * Resolve an entity. + *<p> + * The <code>systemId</code> parameter is used to perform the lookup of the entity as a resource, + * either by interpreting the <code>systemId</code> as an absolute resource path, or by appending + * the last path component of <code>systemId</code> to <code>Constants.SCHEMA_ROOT</code>. + *</p> + * + * @param publicId The public ID of the resource. + * @param systemId The system ID of the resource. + * @return An <code>InputSource</code> from which the entity can be read, or <code>null</code>, if + * the entity could not be found. + * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, java.lang.String) + */ + @Override + public InputSource resolveEntity(final String publicId, String systemId) { + InputStream stream; + int slashPos; + + if (publicId != null) { + // check if we can resolve some standard dtd's + if (publicId.equalsIgnoreCase("-//W3C//DTD XMLSchema 200102//EN")) { + return new InputSource( + getClass().getResourceAsStream(XMLNamespaceConstants.SCHEMA_ROOT + "XMLSchema.dtd")); + } else if (publicId.equalsIgnoreCase("datatypes")) { + return new InputSource( + getClass().getResourceAsStream(XMLNamespaceConstants.SCHEMA_ROOT + "datatypes.dtd")); + } + } else if (systemId != null) { + // get the URI path + try { + final URI uri = new URI(systemId); + systemId = uri.getPath(); + + if (!"file".equals(uri.getScheme()) || "".equals(systemId.trim())) { + return null; + } + + } catch (final MalformedURIException e) { + return null; + } + + // try to get the resource from the full path + stream = getClass().getResourceAsStream(systemId); + if (stream != null) { + final InputSource source = new InputSource(stream); + + source.setSystemId(systemId); + return source; + } + + // try to get the resource from the last path component + slashPos = systemId.lastIndexOf('/'); + if (slashPos >= 0 && systemId.length() > slashPos) { + systemId = systemId.substring(slashPos + 1, systemId.length()); + stream = getClass().getResourceAsStream(XMLNamespaceConstants.SCHEMA_ROOT + systemId); + if (stream != null) { + final InputSource source = new InputSource(stream); + + source.setSystemId(systemId); + return source; + } + } + } + + return null; // nothing found - let the parser handle the entity + } +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java index c50b9e08..d6745c78 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java @@ -1,36 +1,30 @@ -/******************************************************************************* - * 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.utils; import java.util.List; import java.util.Map; - +import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants; +import at.gv.egiz.eaaf.core.exceptions.XPathException; import org.jaxen.JaxenException; import org.jaxen.NamespaceContext; import org.jaxen.Navigator; @@ -43,35 +37,31 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.traversal.NodeIterator; -import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants; -import at.gv.egiz.eaaf.core.exceptions.XPathException; - /** * Utility methods to evaluate XPath expressions on DOM nodes. - * + * * @author Patrick Peck * @version $Id$ */ public class XPathUtils { /** - * The XPath expression selecting all nodes under a given root (including the - * root node itself). + * The XPath expression selecting all nodes under a given root (including the root node itself). */ - public static final String ALL_NODES_XPATH = - "(.//. | .//@* | .//namespace::*)"; + public static final String ALL_NODES_XPATH = "(.//. | .//@* | .//namespace::*)"; /** The <code>DocumentNavigator</code> to use for navigating the document. */ - private static Navigator documentNavigator = - DocumentNavigator.getInstance(); + private static Navigator documentNavigator = DocumentNavigator.getInstance(); /** The default namespace prefix to namespace URI mappings. */ private static NamespaceContext NS_CONTEXT; - - static { - SimpleNamespaceContext ctx = new SimpleNamespaceContext(); + + static { + final SimpleNamespaceContext ctx = new SimpleNamespaceContext(); ctx.addNamespace(XMLNamespaceConstants.MOA_PREFIX, XMLNamespaceConstants.MOA_NS_URI); - ctx.addNamespace(XMLNamespaceConstants.MOA_CONFIG_PREFIX, XMLNamespaceConstants.MOA_CONFIG_NS_URI); - ctx.addNamespace(XMLNamespaceConstants.MOA_ID_CONFIG_PREFIX, XMLNamespaceConstants.MOA_ID_CONFIG_NS_URI); + ctx.addNamespace(XMLNamespaceConstants.MOA_CONFIG_PREFIX, + XMLNamespaceConstants.MOA_CONFIG_NS_URI); + ctx.addNamespace(XMLNamespaceConstants.MOA_ID_CONFIG_PREFIX, + XMLNamespaceConstants.MOA_ID_CONFIG_NS_URI); ctx.addNamespace(XMLNamespaceConstants.SL10_PREFIX, XMLNamespaceConstants.SL10_NS_URI); ctx.addNamespace(XMLNamespaceConstants.SL11_PREFIX, XMLNamespaceConstants.SL11_NS_URI); ctx.addNamespace(XMLNamespaceConstants.SL12_PREFIX, XMLNamespaceConstants.SL12_NS_URI); @@ -82,7 +72,8 @@ public class XPathUtils { ctx.addNamespace(XMLNamespaceConstants.DSIG_PREFIX, XMLNamespaceConstants.DSIG_NS_URI); ctx.addNamespace(XMLNamespaceConstants.XSLT_PREFIX, XMLNamespaceConstants.XSLT_NS_URI); ctx.addNamespace(XMLNamespaceConstants.XSI_PREFIX, XMLNamespaceConstants.XSI_NS_URI); - ctx.addNamespace(XMLNamespaceConstants.DSIG_FILTER2_PREFIX, XMLNamespaceConstants.DSIG_FILTER2_NS_URI); + ctx.addNamespace(XMLNamespaceConstants.DSIG_FILTER2_PREFIX, + XMLNamespaceConstants.DSIG_FILTER2_NS_URI); ctx.addNamespace(XMLNamespaceConstants.DSIG_EC_PREFIX, XMLNamespaceConstants.DSIG_EC_NS_URI); ctx.addNamespace(XMLNamespaceConstants.MD_PREFIX, XMLNamespaceConstants.MD_NS_URI); ctx.addNamespace(XMLNamespaceConstants.MDP_PREFIX, XMLNamespaceConstants.MDP_NS_URI); @@ -94,452 +85,398 @@ public class XPathUtils { ctx.addNamespace(XMLNamespaceConstants.SAML2_PREFIX, XMLNamespaceConstants.SAML2_NS_URI); ctx.addNamespace(XMLNamespaceConstants.SAML2P_PREFIX, XMLNamespaceConstants.SAML2P_NS_URI); ctx.addNamespace(XMLNamespaceConstants.XENC_PREFIX, XMLNamespaceConstants.XENC_NS_URI); - ctx.addNamespace(XMLNamespaceConstants.XADES_1_1_1_NS_PREFIX, XMLNamespaceConstants.XADES_1_1_1_NS_URI); + ctx.addNamespace(XMLNamespaceConstants.XADES_1_1_1_NS_PREFIX, + XMLNamespaceConstants.XADES_1_1_1_NS_URI); NS_CONTEXT = ctx; } /** - * Return a <code>NodeIterator</code> over the nodes matching the XPath - * expression. - * - * All namespace URIs and prefixes declared in the <code>Constants</code> - * interface are used for resolving namespaces. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. + * Return a <code>NodeIterator</code> over the nodes matching the XPath expression. + * + *<p> + * All namespace URIs and prefixes declared in the <code>Constants</code> interface are used for + * resolving namespaces. + *</p> + * + * @param contextNode The root node from which to evaluate the XPath expression. * @param exp The XPath expression to evaluate. * @return An iterator over the resulting nodes. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static NodeIterator selectNodeIterator(Node contextNode, String exp) - throws XPathException { + public static NodeIterator selectNodeIterator(final Node contextNode, final String exp) + throws XPathException { return selectNodeIterator(contextNode, NS_CONTEXT, exp); } /** - * Return a <code>NodeIterator</code> over the nodes matching the XPath - * expression. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. - * @param namespaceElement An element from which to build the - * namespace mapping for evaluating the XPath expression + * Return a <code>NodeIterator</code> over the nodes matching the XPath expression. + * + * @param contextNode The root node from which to evaluate the XPath expression. + * @param namespaceElement An element from which to build the namespace mapping for evaluating the + * XPath expression * @param exp The XPath expression to evaluate. * @return An iterator over the resulting nodes. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static NodeIterator selectNodeIterator( - Node contextNode, - Element namespaceElement, - String exp) - throws XPathException { + public static NodeIterator selectNodeIterator(final Node contextNode, + final Element namespaceElement, final String exp) throws XPathException { try { - SimpleNamespaceContext ctx = new SimpleNamespaceContext(); + final SimpleNamespaceContext ctx = new SimpleNamespaceContext(); ctx.addElementNamespaces(documentNavigator, namespaceElement); return selectNodeIterator(contextNode, ctx, exp); - - } catch (JaxenException e) { - throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); - + + } catch (final JaxenException e) { + throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); + } } /** - * Return a <code>NodeIterator</code> over the nodes matching the XPath - * expression. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. - * @param namespaceMapping A namespace prefix to namespace URI mapping - * (<code>String</code> to <code>String</code>) for evaluating the XPath - * expression. + * Return a <code>NodeIterator</code> over the nodes matching the XPath expression. + * + * @param contextNode The root node from which to evaluate the XPath expression. + * @param namespaceMapping A namespace prefix to namespace URI mapping (<code>String</code> to + * <code>String</code>) for evaluating the XPath expression. * @param exp The XPath expression to evaluate. * @return An iterator over the resulting nodes. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static NodeIterator selectNodeIterator( - Node contextNode, - Map namespaceMapping, - String exp) - throws XPathException { + public static NodeIterator selectNodeIterator(final Node contextNode, final Map namespaceMapping, + final String exp) throws XPathException { - SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping); + final SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping); return selectNodeIterator(contextNode, ctx, exp); } /** - * Return a <code>NodeIterator</code> over the nodes matching the XPath - * expression. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. - * @param nsContext The <code>NamespaceContext</code> for resolving namespace - * prefixes to namespace URIs for evaluating the XPath expression. + * Return a <code>NodeIterator</code> over the nodes matching the XPath expression. + * + * @param contextNode The root node from which to evaluate the XPath expression. + * @param nsContext The <code>NamespaceContext</code> for resolving namespace prefixes to + * namespace URIs for evaluating the XPath expression. * @param exp The XPath expression to evaluate. * @return An iterator over the resulting nodes. * @throws XPathException An error occurred evaluating the XPath expression. */ - private static NodeIterator selectNodeIterator( - Node contextNode, - NamespaceContext nsContext, - String exp) - throws XPathException { + private static NodeIterator selectNodeIterator(final Node contextNode, + final NamespaceContext nsContext, final String exp) throws XPathException { try { - DOMXPath xpath = new DOMXPath(exp); + final DOMXPath xpath = new DOMXPath(exp); List nodes; xpath.setNamespaceContext(nsContext); nodes = xpath.selectNodes(contextNode); return new NodeIteratorAdapter(nodes.listIterator()); - - } catch (JaxenException e) { - throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); - + + } catch (final JaxenException e) { + throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); + } } /** - * Return a <code>NodeList</code> of all the nodes matching the XPath - * expression. - * - * All namespace URIs and prefixes declared in the <code>Constants</code> - * interface are used for resolving namespaces. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. + * Return a <code>NodeList</code> of all the nodes matching the XPath expression. + *<p> + * All namespace URIs and prefixes declared in the <code>Constants</code> interface are used for + * resolving namespaces. + *</p> + * @param contextNode The root node from which to evaluate the XPath expression. * @param exp The XPath expression to evaluate. * @return A <code>NodeList</code> containing the matching nodes. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static NodeList selectNodeList(Node contextNode, String exp) - throws XPathException { + public static NodeList selectNodeList(final Node contextNode, final String exp) + throws XPathException { return selectNodeList(contextNode, NS_CONTEXT, exp); } /** - * Return a <code>NodeList</code> of all the nodes matching the XPath - * expression. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. - * @param namespaceElement An element from which to build the - * namespace mapping for evaluating the XPath expression + * Return a <code>NodeList</code> of all the nodes matching the XPath expression. + * + * @param contextNode The root node from which to evaluate the XPath expression. + * @param namespaceElement An element from which to build the namespace mapping for evaluating the + * XPath expression * @param exp The XPath expression to evaluate. * @return A <code>NodeList</code> containing the matching nodes. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static NodeList selectNodeList( - Node contextNode, - Element namespaceElement, - String exp) - throws XPathException { + public static NodeList selectNodeList(final Node contextNode, final Element namespaceElement, + final String exp) throws XPathException { try { - SimpleNamespaceContext ctx = new SimpleNamespaceContext(); + final SimpleNamespaceContext ctx = new SimpleNamespaceContext(); ctx.addElementNamespaces(documentNavigator, namespaceElement); return selectNodeList(contextNode, ctx, exp); - - } catch (JaxenException e) { - throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); - + + } catch (final JaxenException e) { + throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); + } } /** - * Return a <code>NodeList</code> of all the nodes matching the XPath - * expression. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. - * @param namespaceMapping A namespace prefix to namespace URI mapping - * (<code>String</code> to <code>String</code>) for evaluating the XPath - * expression. + * Return a <code>NodeList</code> of all the nodes matching the XPath expression. + * + * @param contextNode The root node from which to evaluate the XPath expression. + * @param namespaceMapping A namespace prefix to namespace URI mapping (<code>String</code> to + * <code>String</code>) for evaluating the XPath expression. * @param exp The XPath expression to evaluate. * @return A <code>NodeList</code> containing the matching nodes. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static NodeList selectNodeList( - Node contextNode, - Map namespaceMapping, - String exp) - throws XPathException { + public static NodeList selectNodeList(final Node contextNode, final Map namespaceMapping, + final String exp) throws XPathException { - SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping); + final SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping); return selectNodeList(contextNode, ctx, exp); } /** - * Return a <code>NodeList</code> of all the nodes matching the XPath - * expression. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. - * @param nsContext The <code>NamespaceContext</code> for resolving namespace - * prefixes to namespace URIs for evaluating the XPath expression. + * Return a <code>NodeList</code> of all the nodes matching the XPath expression. + * + * @param contextNode The root node from which to evaluate the XPath expression. + * @param nsContext The <code>NamespaceContext</code> for resolving namespace prefixes to + * namespace URIs for evaluating the XPath expression. * @param exp The XPath expression to evaluate. * @return A <code>NodeList</code> containing the matching nodes. * @throws XPathException An error occurred evaluating the XPath expression. */ - private static NodeList selectNodeList(Node contextNode, NamespaceContext nsContext, String exp) throws XPathException { - try { - DOMXPath xpath = new DOMXPath(exp); - List nodes; - xpath.setNamespaceContext(nsContext); - nodes = xpath.selectNodes(contextNode); - return new NodeListAdapter(nodes); - - } catch (JaxenException e) { - throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); - - } + private static NodeList selectNodeList(final Node contextNode, final NamespaceContext nsContext, + final String exp) throws XPathException { + try { + final DOMXPath xpath = new DOMXPath(exp); + List nodes; + xpath.setNamespaceContext(nsContext); + nodes = xpath.selectNodes(contextNode); + return new NodeListAdapter(nodes); + + } catch (final JaxenException e) { + throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); + + } } /** * Select the first node matching an XPath expression. - * - * All namespace URIs and prefixes declared in the <code>Constants</code> - * interface are used for resolving namespaces. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. + *<p> + * All namespace URIs and prefixes declared in the <code>Constants</code> interface are used for + * resolving namespaces. + *</p> + * @param contextNode The root node from which to evaluate the XPath expression. * @param exp The XPath expression to evaluate. - * @return Node The first node matching the XPath expression, or - * <code>null</code>, if no node matched. + * @return Node The first node matching the XPath expression, or <code>null</code>, if no node + * matched. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static Node selectSingleNode(Node contextNode, String exp) - throws XPathException { + public static Node selectSingleNode(final Node contextNode, final String exp) + throws XPathException { return selectSingleNode(contextNode, NS_CONTEXT, exp); } /** * Select the first node matching an XPath expression. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. - * @param namespaceElement An element from which to build the - * namespace mapping for evaluating the XPath expression + * + * @param contextNode The root node from which to evaluate the XPath expression. + * @param namespaceElement An element from which to build the namespace mapping for evaluating the + * XPath expression * @param exp The XPath expression to evaluate. - * @return Node The first node matching the XPath expression, or - * <code>null</code>, if no node matched. + * @return Node The first node matching the XPath expression, or <code>null</code>, if no node + * matched. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static Node selectSingleNode( - Node contextNode, - Element namespaceElement, - String exp) - throws XPathException { + public static Node selectSingleNode(final Node contextNode, final Element namespaceElement, + final String exp) throws XPathException { try { - SimpleNamespaceContext ctx = new SimpleNamespaceContext(); + final SimpleNamespaceContext ctx = new SimpleNamespaceContext(); ctx.addElementNamespaces(documentNavigator, namespaceElement); return selectSingleNode(contextNode, ctx, exp); - - } catch (JaxenException e) { - throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); - + + } catch (final JaxenException e) { + throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); + } } /** * Select the first node matching an XPath expression. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. - * @param namespaceMapping A namespace prefix to namespace URI mapping - * (<code>String</code> to <code>String</code>) for evaluating the XPath - * expression. + * + * @param contextNode The root node from which to evaluate the XPath expression. + * @param namespaceMapping A namespace prefix to namespace URI mapping (<code>String</code> to + * <code>String</code>) for evaluating the XPath expression. * @param exp The XPath expression to evaluate. - * @return Node The first node matching the XPath expression, or - * <code>null</code>, if no node matched. + * @return Node The first node matching the XPath expression, or <code>null</code>, if no node + * matched. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static Node selectSingleNode( - Node contextNode, - Map namespaceMapping, - String exp) - throws XPathException { + public static Node selectSingleNode(final Node contextNode, final Map namespaceMapping, + final String exp) throws XPathException { - SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping); + final SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping); return selectSingleNode(contextNode, ctx, exp); } /** * Select the first node matching an XPath expression. - * - * @param contextNode The root node from which to evaluate the XPath - * expression. - * @param nsContext The <code>NamespaceContext</code> for resolving namespace - * prefixes to namespace URIs for evaluating the XPath expression. + * + * @param contextNode The root node from which to evaluate the XPath expression. + * @param nsContext The <code>NamespaceContext</code> for resolving namespace prefixes to + * namespace URIs for evaluating the XPath expression. * @param exp The XPath expression to evaluate. - * @return Node The first node matching the XPath expression, or - * <code>null</code>, if no node matched. + * @return Node The first node matching the XPath expression, or <code>null</code>, if no node + * matched. * @throws XPathException An error occurred evaluating the XPath expression. */ - public static Node selectSingleNode( - Node contextNode, - NamespaceContext nsContext, - String exp) - throws XPathException { + public static Node selectSingleNode(final Node contextNode, final NamespaceContext nsContext, + final String exp) throws XPathException { try { - DOMXPath xpath = new DOMXPath(exp); + final DOMXPath xpath = new DOMXPath(exp); xpath.setNamespaceContext(nsContext); return (Node) xpath.selectSingleNode(contextNode); - - } catch (JaxenException e) { - throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); - + + } catch (final JaxenException e) { + throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e); + } } /** - * Return the value of a DOM element whose location is given by an XPath - * expression. - * + * Return the value of a DOM element whose location is given by an XPath expression. + * * @param root The root element from which to evaluate the XPath. - * @param xpath The XPath expression pointing to the element whose value - * to return. - * @param def The default value to return, if no element can be found using - * the given <code>xpath</code>. - * @return The element value, if it can be located using the - * <code>xpath</code>. Otherwise, <code>def</code> is returned. + * @param xpath The XPath expression pointing to the element whose value to return. + * @param def The default value to return, if no element can be found using the given + * <code>xpath</code>. + * @return The element value, if it can be located using the <code>xpath</code>. Otherwise, + * <code>def</code> is returned. */ - public static String getElementValue( - Element root, - String xpath, - String def) { + public static String getElementValue(final Element root, final String xpath, final String def) { - Element elem = (Element) XPathUtils.selectSingleNode(root, xpath); - return elem != null ? DOMUtils.getText(elem) : def; + final Element elem = (Element) XPathUtils.selectSingleNode(root, xpath); + return elem != null ? DomUtils.getText(elem) : def; } /** - * Return the value of a DOM attribute whose location is given by an XPath - * expression. - * + * Return the value of a DOM attribute whose location is given by an XPath expression. + * * @param root The root element from which to evaluate the XPath. - * @param xpath The XPath expression pointing to the attribute whose value to - * return. - * @param def The default value to return, if no attribute can be found using - * the given <code>xpath</code>. - * @return The element value, if it can be located using the - * <code>xpath</code>. Otherwise, <code>def</code> is returned. + * @param xpath The XPath expression pointing to the attribute whose value to return. + * @param def The default value to return, if no attribute can be found using the given + * <code>xpath</code>. + * @return The element value, if it can be located using the <code>xpath</code>. Otherwise, + * <code>def</code> is returned. */ - public static String getAttributeValue( - Element root, - String xpath, - String def) { + public static String getAttributeValue(final Element root, final String xpath, final String def) { - Attr attr = (Attr) XPathUtils.selectSingleNode(root, xpath); + final Attr attr = (Attr) XPathUtils.selectSingleNode(root, xpath); return attr != null ? attr.getValue() : def; } - + /** - * Returns the namespace prefix used within <code>XPathUtils</code> for referring to - * the namespace of the specified (Security Layer command) element. - * - * This namespace prefix can be used in various XPath expression evaluation methods - * within <code> XPathUtils</code> without explicitely binding it to the particular - * namespace. - * - * @param contextElement The (Security Layer command) element. - * - * @return the namespace prefix used within <code>XPathUtils</code> for referring to - * the namespace of the specified (Security Layer command) element. - * - * throws XpathException If the specified element has a namespace other than the ones - * known by this implementation as valid Security Layer namespaces (cf. - * @link Constants#SL10_NS_URI, @link Constants#SL11_NS_URI, @link Constants#SL12_NS_URI). + * Returns the namespace prefix used within <code>XPathUtils</code> for referring to the namespace + * of the specified (Security Layer command) element. + *<p> + * This namespace prefix can be used in various XPath expression evaluation methods within + * <code> XPathUtils</code> without explicitely binding it to the particular namespace. + *</p> + * @param contextElement The (Security Layer command) element. + * + * @return the namespace prefix used within <code>XPathUtils</code> for referring to the namespace + * of the specified (Security Layer command) element. + * + * throws XpathException If the specified element has a namespace other than the ones + * known by this implementation as valid Security Layer namespaces (cf. + * @link Constants#SL10_NS_URI, @link Constants#SL11_NS_URI, @link Constants#SL12_NS_URI). */ - public static String getSlPrefix (Element contextElement) throws XPathException - { - String sLNamespace = contextElement.getNamespaceURI(); - String sLPrefix = null; - - if (sLNamespace.equals(XMLNamespaceConstants.SL10_NS_URI)) - sLPrefix = XMLNamespaceConstants.SL10_PREFIX; - - else if (sLNamespace.equals(XMLNamespaceConstants.SL12_NS_URI)) - sLPrefix = XMLNamespaceConstants.SL12_PREFIX; - - else if (sLNamespace.equals(XMLNamespaceConstants.SL11_NS_URI)) - sLPrefix = XMLNamespaceConstants.SL11_PREFIX; - - else - throw new XPathException("XPath operation FAILED. Reason: "); - - return sLPrefix; + public static String getSlPrefix(final Element contextElement) throws XPathException { + final String sLNamespace = contextElement.getNamespaceURI(); + String slPrefix = null; + + if (sLNamespace.equals(XMLNamespaceConstants.SL10_NS_URI)) { + slPrefix = XMLNamespaceConstants.SL10_PREFIX; + } else if (sLNamespace.equals(XMLNamespaceConstants.SL12_NS_URI)) { + slPrefix = XMLNamespaceConstants.SL12_PREFIX; + } else if (sLNamespace.equals(XMLNamespaceConstants.SL11_NS_URI)) { + slPrefix = XMLNamespaceConstants.SL11_PREFIX; + } else { + throw new XPathException("XPath operation FAILED. Reason: "); + } + + return slPrefix; } - - + + /** - * Return the SecurityLayer namespace prefix of the context element. - * If the context element is not the element that lies within the - * SecurityLayer namespace. The Securitylayer namespace is derived from - * the <code>xmlns:sl10</code>, <code>sl11</code> or <code>sl</code> - * attribute of the context element. - * + * Return the SecurityLayer namespace prefix of the context element. If the context element is not + * the element that lies within the SecurityLayer namespace. The Securitylayer namespace is + * derived from the <code>xmlns:sl10</code>, <code>sl11</code> or <code>sl</code> attribute of the + * context element. + *<p> * The returned prefix is needed for evaluating XPATH expressions. - * - * @param contextElement The element to get a prefix for the Securitylayer namespace, - * that is used within the corresponding document. - * - * @return The string <code>sl10</code>, <code>sl11</code> or <code>sl</code>, - * depending on the SecurityLayer namespace of the contextElement. - * - * throws XPathException If no (vlalid) SecurityLayer namespace prefix or namespace - * is defined. + *</p> + * @param contextElement The element to get a prefix for the Securitylayer namespace, that is used + * within the corresponding document. + * + * @return The string <code>sl10</code>, <code>sl11</code> or <code>sl</code>, depending on the + * SecurityLayer namespace of the contextElement. + * + * throws XPathException If no (vlalid) SecurityLayer namespace prefix or namespace is + * defined. */ - public static String getSlPrefixFromNoRoot (Element contextElement) throws XPathException { - - String slPrefix = checkSLnsDeclaration(contextElement, XMLNamespaceConstants.SL10_PREFIX, XMLNamespaceConstants.SL10_NS_URI); - if (slPrefix == null) - slPrefix = checkSLnsDeclaration(contextElement, XMLNamespaceConstants.SL11_PREFIX, XMLNamespaceConstants.SL11_NS_URI); - - if (slPrefix == null) - slPrefix = checkSLnsDeclaration(contextElement, XMLNamespaceConstants.SL12_PREFIX, XMLNamespaceConstants.SL12_NS_URI); - + public static String getSlPrefixFromNoRoot(final Element contextElement) throws XPathException { + + String slPrefix = checkSLnsDeclaration(contextElement, XMLNamespaceConstants.SL10_PREFIX, + XMLNamespaceConstants.SL10_NS_URI); + if (slPrefix == null) { + slPrefix = checkSLnsDeclaration(contextElement, XMLNamespaceConstants.SL11_PREFIX, + XMLNamespaceConstants.SL11_NS_URI); + } + + if (slPrefix == null) { + slPrefix = checkSLnsDeclaration(contextElement, XMLNamespaceConstants.SL12_PREFIX, + XMLNamespaceConstants.SL12_NS_URI); + } + return slPrefix; - + } - + /** - * Checks if the context element has an attribute <code>xmlns:slPrefix</code> and - * if the prefix of that attribute corresponds with a valid SecurityLayer namespace. - * - * @param contextElement The element to be checked. - * @param slPrefix The prefix which should be checked. Must be a valid SecurityLayer - * namespace prefix. - * @param slNameSpace The SecurityLayer namespace that corresponds to the specified prefix. - * - * @return The valid SecurityLayer prefix or <code>null</code> if this prefix is - * not used. - * @throws XPathException + * Checks if the context element has an attribute <code>xmlns:slPrefix</code> and if the prefix of + * that attribute corresponds with a valid SecurityLayer namespace. + * + * @param contextElement The element to be checked. + * @param slPrefix The prefix which should be checked. Must be a valid SecurityLayer namespace + * prefix. + * @param slNameSpace The SecurityLayer namespace that corresponds to the specified prefix. + * + * @return The valid SecurityLayer prefix or <code>null</code> if this prefix is not used. + * @throws XPathException In case of an error */ - private static String checkSLnsDeclaration(Element contextElement, String slPrefix, String slNameSpace) - throws XPathException - { - String nsAtt = "xmlns:" + slPrefix; - String nameSpace = contextElement.getAttribute(nsAtt); + private static String checkSLnsDeclaration(final Element contextElement, final String slPrefix, + final String slNameSpace) throws XPathException { + final String nsAtt = "xmlns:" + slPrefix; + final String nameSpace = contextElement.getAttribute(nsAtt); if (nameSpace == "") { return null; - + } else { // check if namespace is correct - if (nameSpace.equals(slNameSpace)) + if (nameSpace.equals(slNameSpace)) { return slPrefix; - else - throw new XPathException("Unknown Namespace declaration"); + } else { + throw new XPathException("Unknown Namespace declaration"); + } } } |