diff options
author | Pierre-Charles David | 2017-05-03 09:09:19 +0000 |
---|---|---|
committer | Pierre-Charles David | 2017-05-11 13:40:55 +0000 |
commit | 055cae502c47e5cd91a9bcde0d298ccfb492e32e (patch) | |
tree | 834d9a0cbca3fb424e2f2fd826672d51a4ffc704 | |
parent | 924a5f6367f4bd025c3f115626dff607d4dca006 (diff) | |
download | org.eclipse.sirius-055cae502c47e5cd91a9bcde0d298ccfb492e32e.tar.gz org.eclipse.sirius-055cae502c47e5cd91a9bcde0d298ccfb492e32e.tar.xz org.eclipse.sirius-055cae502c47e5cd91a9bcde0d298ccfb492e32e.zip |
[495036] Add EvaluationErrorHandler to SessionInterpreter
Add a configurable EvaluationErrorHandler to SessionInterpreter, which
is invoked/consulted on every exception occuring while evaluating an
expression. The default value does nothing, and any exception
occurring is simply re-thrown as before.
Bug: 495036
Change-Id: I19d55ebeb1821b2257e230d354cb3cc9ae052ad7
Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
4 files changed, 242 insertions, 39 deletions
diff --git a/plugins/org.eclipse.sirius/plugin.properties b/plugins/org.eclipse.sirius/plugin.properties index 2976dd058e..b8bbf909e6 100644 --- a/plugins/org.eclipse.sirius/plugin.properties +++ b/plugins/org.eclipse.sirius/plugin.properties @@ -241,6 +241,7 @@ SessionResourcesSynchronizer_cantHandleResourceChangeMsg = Can''t handle resourc SessionResourcesSynchronizer_reloadOperationFailErrorMsg = a reload operation failed for unknown reason SessionResourcesTracker_addReferencedSemanticResourcesMsg = Add referenced semantic resources SessionResourcesTracker_semanticResourcesAccessErrorMsg = Error while accessing semantic resources +SessionInterpreter_evaluationError = Error while evaluating expression SessionVSMUpdater_VSMLoadErrorMsg = Unable to load the VSM at {0} SetValueTask_label = Set a value SiriusControlCommand_controlResourceMsg = Control resource diff --git a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/internal/interpreter/EvaluationErrorHandler.java b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/internal/interpreter/EvaluationErrorHandler.java new file mode 100644 index 0000000000..ac10135f0a --- /dev/null +++ b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/internal/interpreter/EvaluationErrorHandler.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2017 Obeo. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.sirius.tools.internal.interpreter; + +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.sirius.viewpoint.SiriusPlugin; + +/** + * Allows client code to decide how errors occuring during expression evaluation should be treated. + * + * @author pcdavid + */ +public abstract class EvaluationErrorHandler { + /** + * Standard handler that ignores any exception. + */ + public static final EvaluationErrorHandler IGNORE = new EvaluationErrorHandler() { + @Override + public void handleException(Exception ex) { + // Ignore. + } + }; + + /** + * Standard handler that triggers a rollback of the current transaction. + */ + public static final EvaluationErrorHandler ROLLBACK = new EvaluationErrorHandler() { + @Override + public void handleException(Exception ex) { + requestTransactionRollback(ex); + } + }; + + /** + * Invoked when an expression's evaluation throws an exception. + * + * @param ex + * the unexpected exception which occurred during an operation. + * @throws RuntimeException + * if the handler decides that the correct behavior is to throw a real exception (the original one or + * another). + */ + public abstract void handleException(Exception ex); + + /** + * Can be used to log an error in the system log. + * + * @param message + * the message to log. + * @param ex + * the error. + */ + protected void logError(String message, Exception ex) { + SiriusPlugin.getDefault().error(message, ex); + } + + /** + * Can be used to log a warning in the system log. + * + * @param message + * the message to log. + * @param ex + * the error. + */ + protected void logWarning(String message, Exception ex) { + SiriusPlugin.getDefault().warning(message, ex); + } + + /** + * Can be used when the exception occured inside an EMF Transaction to request all the changes previously made in + * the transaction to be rolled back. This throws an exception and thus should be the last method called from + * {@link #handleException(EObject, String, Exception)}. + * + * @param cause + * the root cause. + */ + protected void requestTransactionRollback(Exception cause) { + RuntimeException cancel = new OperationCanceledException(); + cancel.initCause(cause); + throw cancel; + } + +} diff --git a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/internal/interpreter/SessionInterpreter.java b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/internal/interpreter/SessionInterpreter.java index 674ce1559d..875d906017 100644 --- a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/internal/interpreter/SessionInterpreter.java +++ b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/internal/interpreter/SessionInterpreter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2016 THALES GLOBAL SERVICES and others. + * Copyright (c) 2010, 2017 THALES GLOBAL SERVICES and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -17,7 +17,9 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicReference; +import org.eclipse.emf.common.util.BasicDiagnostic; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.ECrossReferenceAdapter; @@ -39,6 +41,8 @@ import org.eclipse.sirius.common.tools.api.profiler.ProfilerTask; import org.eclipse.sirius.ecore.extender.business.api.accessor.MetamodelDescriptor; import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor; import org.eclipse.sirius.tools.api.profiler.SiriusTasksKey; +import org.eclipse.sirius.viewpoint.Messages; +import org.eclipse.sirius.viewpoint.SiriusPlugin; import com.google.common.collect.Sets; @@ -56,8 +60,8 @@ public class SessionInterpreter implements IInterpreter, IProposalProvider, IInt private Collection<String> dependencies = Sets.newLinkedHashSet(); /** - * If Sirius knows of any additional metamodel that may be necessary for the - * interpreter, they'll be registered here. + * If Sirius knows of any additional metamodel that may be necessary for the interpreter, they'll be registered + * here. */ private Collection<MetamodelDescriptor> additionalMetamodels = Sets.newLinkedHashSet(); @@ -79,6 +83,26 @@ public class SessionInterpreter implements IInterpreter, IProposalProvider, IInt /** The profiler tasks. */ private final Map<String, ProfilerTask> profilerTasks = new HashMap<String, ProfilerTask>(); + private AtomicReference<EvaluationErrorHandler> evaluationErrorHandler = new AtomicReference<>(EvaluationErrorHandler.IGNORE); + + /** + * Executes some code in a context where interpreted expression errors are handled by the given + * EvaluationErrorHandler. + * + * @param handler + * the handler for evaluation errors occuring while executing the code. + * @param body + * the code to execute. + */ + public void withErrorHandler(EvaluationErrorHandler handler, Runnable body) { + EvaluationErrorHandler old = this.evaluationErrorHandler.getAndSet(handler); + try { + body.run(); + } finally { + this.evaluationErrorHandler.compareAndSet(handler, old); + } + } + @Override public void activateMetamodels(Collection<MetamodelDescriptor> metamodels) { this.additionalMetamodels.addAll(metamodels); @@ -120,74 +144,158 @@ public class SessionInterpreter implements IInterpreter, IProposalProvider, IInt @Override public IEvaluationResult evaluateExpression(final EObject target, final String expression) throws EvaluationException { final IInterpreter interpreter = getInterpreter(expression); - if (interpreter instanceof IInterpreterWithDiagnostic) { - return ((IInterpreterWithDiagnostic) interpreter).evaluateExpression(target, expression); + IEvaluationResult result = null; + try { + if (interpreter instanceof IInterpreterWithDiagnostic) { + result = ((IInterpreterWithDiagnostic) interpreter).evaluateExpression(target, expression); + } else { + // Fall back on the default behavior otherwise with an OK diagnostic + final Object value = interpreter.evaluate(target, expression); + result = new IEvaluationResult() { + @Override + public Object getValue() { + return value; + } + + @Override + public Diagnostic getDiagnostic() { + return Diagnostic.OK_INSTANCE; + } + }; + } + } catch (EvaluationException evx) { + this.evaluationErrorHandler.get().handleException(evx); + result = creatErrorResult(evx); + // CHECKSTYLE:OFF + } catch (RuntimeException rex) { + // CHECKSTYLE:ON + this.evaluationErrorHandler.get().handleException(rex); + result = creatErrorResult(rex); } + return result; + } - // Fall back on the default behavior otherwise with an OK diagnostic - final Object result = interpreter.evaluate(target, expression); - - IEvaluationResult evaluationResult = new IEvaluationResult() { + private IEvaluationResult creatErrorResult(Exception ex) { + final BasicDiagnostic diag = new BasicDiagnostic(Diagnostic.ERROR, SiriusPlugin.ID, 0, Messages.SessionInterpreter_evaluationError, new Object[] { ex }); + return new IEvaluationResult() { @Override public Object getValue() { - return result; + return null; } - @Override public Diagnostic getDiagnostic() { - return Diagnostic.OK_INSTANCE; + return diag; } }; - - return evaluationResult; } @Override public Object evaluate(final EObject target, final String expression) throws EvaluationException { - preEvaluation(expression); - final Object evaluate = getInterpreter(expression).evaluate(target, expression); - postEvaluation(expression); - return evaluate; + try { + preEvaluation(expression); + final Object evaluate = getInterpreter(expression).evaluate(target, expression); + postEvaluation(expression); + return evaluate; + } catch (EvaluationException evx) { + this.evaluationErrorHandler.get().handleException(evx); + throw evx; + // CHECKSTYLE:OFF + } catch (RuntimeException rex) { + // CHECKSTYLE:ON + this.evaluationErrorHandler.get().handleException(rex); + throw rex; + } } @Override public boolean evaluateBoolean(final EObject context, final String expression) throws EvaluationException { - preEvaluation(expression); - final boolean evaluateBoolean = getInterpreter(expression).evaluateBoolean(context, expression); - postEvaluation(expression); - return evaluateBoolean; + try { + preEvaluation(expression); + final boolean evaluateBoolean = getInterpreter(expression).evaluateBoolean(context, expression); + postEvaluation(expression); + return evaluateBoolean; + } catch (EvaluationException evx) { + this.evaluationErrorHandler.get().handleException(evx); + throw evx; + // CHECKSTYLE:OFF + } catch (RuntimeException rex) { + // CHECKSTYLE:ON + this.evaluationErrorHandler.get().handleException(rex); + throw rex; + } + } @Override public Collection<EObject> evaluateCollection(final EObject context, final String expression) throws EvaluationException { - preEvaluation(expression); - final Collection<EObject> evaluateCollection = getInterpreter(expression).evaluateCollection(context, expression); - postEvaluation(expression); - return evaluateCollection; + try { + preEvaluation(expression); + final Collection<EObject> evaluateCollection = getInterpreter(expression).evaluateCollection(context, expression); + postEvaluation(expression); + return evaluateCollection; + } catch (EvaluationException evx) { + this.evaluationErrorHandler.get().handleException(evx); + throw evx; + // CHECKSTYLE:OFF + } catch (RuntimeException rex) { + // CHECKSTYLE:ON + this.evaluationErrorHandler.get().handleException(rex); + throw rex; + } } @Override public EObject evaluateEObject(final EObject context, final String expression) throws EvaluationException { - preEvaluation(expression); - final EObject evaluateEObject = getInterpreter(expression).evaluateEObject(context, expression); - postEvaluation(expression); - return evaluateEObject; + try { + preEvaluation(expression); + final EObject evaluateEObject = getInterpreter(expression).evaluateEObject(context, expression); + postEvaluation(expression); + return evaluateEObject; + } catch (EvaluationException evx) { + this.evaluationErrorHandler.get().handleException(evx); + throw evx; + // CHECKSTYLE:OFF + } catch (RuntimeException rex) { + // CHECKSTYLE:ON + this.evaluationErrorHandler.get().handleException(rex); + throw rex; + } } @Override public Integer evaluateInteger(final EObject context, final String expression) throws EvaluationException { - preEvaluation(expression); - final Integer evaluateInteger = getInterpreter(expression).evaluateInteger(context, expression); - postEvaluation(expression); - return evaluateInteger; + try { + preEvaluation(expression); + final Integer evaluateInteger = getInterpreter(expression).evaluateInteger(context, expression); + postEvaluation(expression); + return evaluateInteger; + } catch (EvaluationException evx) { + this.evaluationErrorHandler.get().handleException(evx); + throw evx; + // CHECKSTYLE:OFF + } catch (RuntimeException rex) { + // CHECKSTYLE:ON + this.evaluationErrorHandler.get().handleException(rex); + throw rex; + } } @Override public String evaluateString(final EObject context, final String expression) throws EvaluationException { - preEvaluation(expression); - final String evaluateString = getInterpreter(expression).evaluateString(context, expression); - postEvaluation(expression); - return evaluateString; + try { + preEvaluation(expression); + String evaluateString = getInterpreter(expression).evaluateString(context, expression); + postEvaluation(expression); + return evaluateString; + } catch (EvaluationException evx) { + this.evaluationErrorHandler.get().handleException(evx); + throw evx; + // CHECKSTYLE:OFF + } catch (RuntimeException rex) { + // CHECKSTYLE:ON + this.evaluationErrorHandler.get().handleException(rex); + throw rex; + } } @Override @@ -393,5 +501,4 @@ public class SessionInterpreter implements IInterpreter, IProposalProvider, IInt } } } - } diff --git a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/Messages.java b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/Messages.java index 116716945c..6cecb0d926 100644 --- a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/Messages.java +++ b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/Messages.java @@ -497,6 +497,9 @@ public final class Messages { @TranslatableMessage public static String SessionFactoryImpl_sessionLoadingMsg; + + @TranslatableMessage + public static String SessionInterpreter_evaluationError; @TranslatableMessage public static String SessionManagerImpl_remoteServerConnectionErrorMsg; |