/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.studio.concurrency.internal; import java.util.List; import java.util.concurrent.ExecutionException; import com.rapidminer.Process; import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorException; import com.rapidminer.operator.PortUserError; import com.rapidminer.operator.UserError; import com.rapidminer.operator.ports.InputPort; import com.rapidminer.operator.ports.OutputPort; import com.rapidminer.operator.ports.Port; /** * Helper class for exception handling when using {@link ConcurrencyExecutionService}. * <p> * Note that this part of the API is only temporary and might be removed in future versions again. * </p> * * @author Sebastian Land * @since 7.4 * @see ConcurrencyExecutionServiceProvider Provider to get the concurrency execution service */ public enum ExecutionExceptionHandling { /** the singleton instance */ INSTANCE; /** * Tries to get the underlying cause of an {@link ExecutionException} which occurred while using * {@link ConcurrencyExecutionServiceProvider}. * * @param e * the exception which occurred during execution via * {@link ConcurrencyExecutionService} methods. * @param process * the process in which the exception occurred * @return the {@link UserError} or {@link OperatorException} that caused the execution * exception. * @throws OperatorException * if the execution exception cannot be processed. * @throws RuntimeException * if the cause of the exception was a runtime exception * @throws Error * if the cause of the exception was an error */ public OperatorException processExecutionException(ExecutionException e, Process process) throws OperatorException, RuntimeException, Error { // unpack stacked execution exceptions Throwable cause = e.getCause(); while (cause != null && cause != cause.getCause() && cause instanceof ExecutionException) { cause = cause.getCause(); } if (cause != null) { // unpack runtime exceptions if necessary Throwable innerCause = cause; while (innerCause != null && innerCause != innerCause.getCause() && innerCause instanceof RuntimeException) { // we'll assume the cause is the actual nested exception innerCause = innerCause.getCause(); } // if the inner cause is an instance of an operator exception // we'll handle this exception as root cause if (innerCause instanceof OperatorException) { cause = innerCause; } // try to re-map the operator and port to the original process if (cause instanceof UserError) { UserError error = (UserError) cause; Operator sourceOperator = error.getOperator(); if (process != null && sourceOperator != null) { error.setOperator(process.getOperator(sourceOperator.getName())); } if (sourceOperator != null && cause instanceof PortUserError) { PortUserError portError = (PortUserError) error; List<InputPort> inputPorts = sourceOperator.getInputPorts().getAllPorts(); Port errorPort = portError.getPort(); boolean portFound = false; for (int i = 0; i < inputPorts.size(); i++) { if (inputPorts.get(i).equals(errorPort)) { portError.setPort(error.getOperator().getInputPorts().getAllPorts().get(i)); portFound = true; break; } } if (!portFound) { List<OutputPort> outputPorts = sourceOperator.getOutputPorts().getAllPorts(); for (int i = 0; i < outputPorts.size(); i++) { if (outputPorts.get(i).equals(errorPort)) { portError.setPort(error.getOperator().getOutputPorts().getAllPorts().get(i)); break; } } } } return error; } else if (cause instanceof OperatorException) { return (OperatorException) cause; } else if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } } return new OperatorException("There seems to be an unknown problem", cause); } }