From de346dcf4b4571017eb6700453d876c2e9940195 Mon Sep 17 00:00:00 2001 From: Alena Laskavaia Date: Fri, 11 Mar 2011 03:18:21 +0000 Subject: [PATCH] refactor bunch of stuff to support profiles better - not problem (kind) knows about parent category and its profile --- .../.settings/org.eclipse.jdt.ui.prefs | 4 +- .../cdt/codan/core/model/IProblemElement.java | 19 +++- .../cdt/codan/core/model/IProblemProfile.java | 14 +++ .../model/IProblemProfileChangeListener.java | 33 ++++++ .../core/model/ProblemProfileChangeEvent.java | 104 ++++++++++++++++++ .../internal/core/model/CodanProblem.java | 53 ++++----- .../core/model/CodanProblemCategory.java | 60 +++++++++- .../core/model/CodanProblemElement.java | 96 ++++++++++++++++ .../internal/core/model/ProblemProfile.java | 84 +++++++++++++- 9 files changed, 424 insertions(+), 43 deletions(-) create mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemProfileChangeListener.java create mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ProblemProfileChangeEvent.java create mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemElement.java diff --git a/codan/org.eclipse.cdt.codan.core/.settings/org.eclipse.jdt.ui.prefs b/codan/org.eclipse.cdt.codan.core/.settings/org.eclipse.jdt.ui.prefs index 1b4ba7b4d85..94c50da6076 100644 --- a/codan/org.eclipse.cdt.codan.core/.settings/org.eclipse.jdt.ui.prefs +++ b/codan/org.eclipse.cdt.codan.core/.settings/org.eclipse.jdt.ui.prefs @@ -1,4 +1,4 @@ -#Wed Feb 23 19:43:25 EST 2011 +#Thu Mar 10 20:04:36 EST 2011 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_Eclipse [built-in] - Alena @@ -18,7 +18,7 @@ sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false sp_cleanup.convert_to_enhanced_for_loop=false sp_cleanup.correct_indentation=false -sp_cleanup.format_source_code=false +sp_cleanup.format_source_code=true sp_cleanup.format_source_code_changes_only=false sp_cleanup.make_local_variable_final=false sp_cleanup.make_parameters_final=false diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemElement.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemElement.java index d0dc3611125..a48f6000abc 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemElement.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Alena Laskavaia + * Copyright (c) 2009, 2010 Alena Laskavaia * 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 @@ -11,7 +11,8 @@ package org.eclipse.cdt.codan.core.model; /** - * Problem category {@link IProblemCategory} or problem {@link IProblem} + * Problem element represents problem category {@link IProblemCategory} or + * problem {@link IProblem} * * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. @@ -26,4 +27,18 @@ public interface IProblemElement extends Cloneable { * but it should NOT throw it */ Object clone() throws CloneNotSupportedException; + + /** + * @return problem profile where element belongs, can return null if profile + * is not define for some reason + * @since 2.0 + */ + IProblemProfile getProfile(); + + /** + * @return problem category where element belongs for a give profile, can + * return null if profile is not define + * @since 2.0 + */ + IProblemCategory getParentCategory(); } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemProfile.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemProfile.java index 1a0d2dfee20..aac4a34c9d0 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemProfile.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemProfile.java @@ -65,4 +65,18 @@ public interface IProblemProfile extends IProblemElement { * @return array of problems defined in profile */ IProblem[] getProblems(); + + /** + * Add a listener for profile changes + * @param listener + * @since 2.0 + */ + public void addProfileChangeListener(IProblemProfileChangeListener listener); + + /** + * Remove a lister for profile changes + * @param listener + * @since 2.0 + */ + public void removeProfileChangeListener(IProblemProfileChangeListener listener); } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemProfileChangeListener.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemProfileChangeListener.java new file mode 100644 index 00000000000..fc9d8de34b0 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemProfileChangeListener.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009, 2011 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.model; + +/** + * A listener used to receive changes to problem profile + *

+ * Clients may implement this interface. + *

+ * + * @since 2.0 + */ +public interface IProblemProfileChangeListener { + /** + * Notification that a profile value has changed. + * The given event object describes the change details and must not + * be null. + * + * @param event the event details + * @see ProblemProfileChangeEvent + * @see IProblemProfile#addProfileChangeListener(IProblemProfileChangeListener) + * @see IProblemProfile#removeProfileChangeListener(IProblemProfileChangeListener) + */ + public void profileChange(ProblemProfileChangeEvent event); +} \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ProblemProfileChangeEvent.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ProblemProfileChangeEvent.java new file mode 100644 index 00000000000..441f22e730e --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ProblemProfileChangeEvent.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2009, 2011 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.model; + +import java.util.EventObject; + +import org.eclipse.core.resources.IResource; + +/** + * An event object describing the details of a change to a preference + * in the preference store. + * + * @noextend This class is not intended to be extended by clients. + * @since 2.0 + */ +public final class ProblemProfileChangeEvent extends EventObject { + /** + * All serializable objects should have a stable serialVersionUID + */ + private static final long serialVersionUID = 1L; + private String key; + private Object newValue; + private Object oldValue; + private IResource resourse; + private IProblemProfile profile; + public static final String PROBLEM_KEY = "problem"; //$NON-NLS-1$ + public static final String PROBLEM_PREF_KEY = "problem_params"; //$NON-NLS-1$ + + /** + * Constructor for a new profile change event. The node and the + * key must not be null. + * + * @param profile the profile on which the change occurred + * @param resource the resource for which profile changes occurred + * @param key the preference key + * @param oldValue the old preference value + * @param newValue the new preference value + */ + public ProblemProfileChangeEvent(IProblemProfile profile, IResource resource, String key, Object oldValue, Object newValue) { + super(profile); + this.key = key; + this.newValue = newValue; + this.oldValue = oldValue; + this.profile = profile; + this.resourse = resource; + } + + /** + * Return the resource on which the change occurred. + * Must not be null. + * + * @return the node + */ + public IResource getResource() { + return resourse; + } + + /** + * @return profile + */ + public IProblemProfile getProfile() { + return profile; + } + + /** + * Return the key of the preference which was changed. + * Must not be null. + * + * @return the preference key + */ + public String getKey() { + return key; + } + + /** + * Return the new value for the preference encoded as a + * String, or null if the + * preference was removed. + * + * @return the new value or null + */ + public Object getNewValue() { + return newValue; + } + + /** + * Return the old value for the preference encoded as a + * String, or null if the + * preference was removed or if it cannot be determined. + * + * @return the old value or null + */ + public Object getOldValue() { + return oldValue; + } +} \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java index ab98e04f733..652c6645fc0 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java @@ -13,19 +13,19 @@ package org.eclipse.cdt.codan.internal.core.model; import org.eclipse.cdt.codan.core.model.CodanSeverity; import org.eclipse.cdt.codan.core.model.IProblemReporter; import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy; +import org.eclipse.cdt.codan.core.model.ProblemProfileChangeEvent; import org.eclipse.cdt.codan.core.param.IProblemPreference; /** * A type of problems reported by Codan. */ -public class CodanProblem implements IProblemWorkingCopy, Cloneable { +public class CodanProblem extends CodanProblemElement implements IProblemWorkingCopy, Cloneable { private String id; private String name; private String messagePattern; private CodanSeverity severity = CodanSeverity.Warning; private boolean enabled = true; - private IProblemPreference preference; - private boolean frozen; + private IProblemPreference rootPreference; private String description; private String markerType = IProblemReporter.GENERIC_CODE_ANALYSIS_MARKER_TYPE; @@ -40,7 +40,6 @@ public class CodanProblem implements IProblemWorkingCopy, Cloneable { public CodanProblem(String problemId, String name) { this.id = problemId; this.name = name; - this.frozen = false; } public String getName() { @@ -63,55 +62,52 @@ public class CodanProblem implements IProblemWorkingCopy, Cloneable { public void setSeverity(CodanSeverity sev) { if (sev == null) throw new NullPointerException(); + checkSet(); this.severity = sev; + notifyChanged(ProblemProfileChangeEvent.PROBLEM_KEY); } public void setEnabled(boolean checked) { + checkSet(); this.enabled = checked; + notifyChanged(ProblemProfileChangeEvent.PROBLEM_KEY); } /* * (non-Javadoc) - * + * * @see java.lang.Object#clone() */ @Override public Object clone() { CodanProblem prob; - try { - prob = (CodanProblem) super.clone(); - if (preference != null) { - prob.preference = (IProblemPreference) preference.clone(); - } - return prob; - } catch (CloneNotSupportedException e) { - throw new RuntimeException(); // not possible + prob = (CodanProblem) super.clone(); + if (rootPreference != null) { + prob.rootPreference = (IProblemPreference) rootPreference.clone(); } + return prob; } public void setPreference(IProblemPreference value) { - if (value==null) + if (value == null) throw new NullPointerException(); - preference = value; + rootPreference = value; + notifyChanged(ProblemProfileChangeEvent.PROBLEM_PREF_KEY); } public IProblemPreference getPreference() { - return preference; + return rootPreference; } /* * (non-Javadoc) - * + * * @see org.eclipse.cdt.codan.core.model.IProblem#getMessagePattern() */ public String getMessagePattern() { return messagePattern; } - protected void freeze() { - frozen = true; - } - /** * @param messagePattern * the message to set @@ -121,14 +117,9 @@ public class CodanProblem implements IProblemWorkingCopy, Cloneable { this.messagePattern = messagePattern; } - protected void checkSet() { - if (frozen) - throw new IllegalStateException("Object is unmodifieble"); //$NON-NLS-1$ - } - /* * (non-Javadoc) - * + * * @see org.eclipse.cdt.codan.core.model.IProblem#getDescription() */ public String getDescription() { @@ -137,18 +128,19 @@ public class CodanProblem implements IProblemWorkingCopy, Cloneable { /* * (non-Javadoc) - * + * * @see * org.eclipse.cdt.codan.core.model.IProblemWorkingCopy#setDescription(java * .lang.String) */ public void setDescription(String desc) { + checkSet(); this.description = desc; } /* * (non-Javadoc) - * + * * @see org.eclipse.cdt.codan.core.model.IProblem#getMarkerType() */ public String getMarkerType() { @@ -157,10 +149,11 @@ public class CodanProblem implements IProblemWorkingCopy, Cloneable { /** * Sets the marker id for the problem. - * + * * @param markerType */ public void setMarkerType(String markerType) { + checkSet(); this.markerType = markerType; } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java index 57320f5257e..c5fc8ff30f5 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Alena Laskavaia + * Copyright (c) 2009, 2010 Alena Laskavaia * 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,8 +17,12 @@ import java.util.Iterator; import org.eclipse.cdt.codan.core.model.IProblem; import org.eclipse.cdt.codan.core.model.IProblemCategory; import org.eclipse.cdt.codan.core.model.IProblemElement; +import org.eclipse.cdt.codan.core.model.IProblemProfile; -public class CodanProblemCategory implements IProblemCategory, Cloneable { +/** + * TODO: add description + */ +public class CodanProblemCategory extends CodanProblemElement implements IProblemCategory, Cloneable { private String id; private String name; private ArrayList list = new ArrayList(); @@ -47,6 +51,11 @@ public class CodanProblemCategory implements IProblemCategory, Cloneable { public void addChild(IProblemElement p) { list.add(p); + if (p instanceof CodanProblemElement) { + CodanProblemElement cce = (CodanProblemElement) p; + cce.setParentCategory(this); + cce.setProfile(getProfile()); + } } public static IProblem findProblem(IProblemCategory c, String id) { @@ -116,15 +125,54 @@ public class CodanProblemCategory implements IProblemCategory, Cloneable { @Override public Object clone() { try { - CodanProblemCategory clone = (CodanProblemCategory) super.clone(); - clone.list = new ArrayList(); + CodanProblemCategory catClone = (CodanProblemCategory) super.clone(); + catClone.list = new ArrayList(); for (Iterator iterator = this.list.iterator(); iterator.hasNext();) { IProblemElement child = iterator.next(); - clone.list.add((IProblemElement) child.clone()); + IProblemElement childClone = (IProblemElement) child.clone(); + if (childClone instanceof CodanProblemElement) { + CodanProblemElement cce = (CodanProblemElement) childClone; + boolean fro = cce.isFrozen(); + cce.setFrozen(false); + cce.setParentCategory(catClone); + cce.setFrozen(fro); + } + catClone.list.add(childClone); } - return clone; + return catClone; } catch (CloneNotSupportedException e) { return this; } } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.cdt.codan.internal.core.model.CodanProblemElement#setProfile + * (org.eclipse.cdt.codan.core.model.IProblemProfile) + */ + @Override + public void setProfile(IProblemProfile profile) { + checkSet(); + super.setProfile(profile); + for (Iterator iterator = this.list.iterator(); iterator.hasNext();) { + IProblemElement child = iterator.next(); + if (child instanceof CodanProblemElement) { + ((CodanProblemElement) child).setProfile(profile); + } + } + } + + @Override + public void setFrozen(boolean b) { + checkSet(); + super.setFrozen(b); + for (Iterator iterator = this.list.iterator(); iterator.hasNext();) { + IProblemElement child = iterator.next(); + if (child instanceof CodanProblemElement) { + ((CodanProblemElement) child).setFrozen(b); + } + } + } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemElement.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemElement.java new file mode 100644 index 00000000000..222e7749f84 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemElement.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.core.model; + +import org.eclipse.cdt.codan.core.model.IProblemCategory; +import org.eclipse.cdt.codan.core.model.IProblemElement; +import org.eclipse.cdt.codan.core.model.IProblemProfile; + +/** + * base class for category and problem + */ +public class CodanProblemElement implements IProblemElement { + private IProblemProfile profile; + private IProblemCategory parent; + private boolean frozen = false; + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.codan.core.model.IProblemElement#getProfile() + */ + public IProblemProfile getProfile() { + return profile; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.codan.core.model.IProblemElement#getCategory() + */ + public IProblemCategory getParentCategory() { + return parent; + } + + /** + * @param profile - parent profile + */ + public void setProfile(IProblemProfile profile) { + checkSet(); + this.profile = profile; + } + + /** + * @param parent - parent category + */ + public void setParentCategory(IProblemCategory parent) { + checkSet(); + this.parent = parent; + } + + @Override + public Object clone() { + try { + CodanProblemElement prob = (CodanProblemElement) super.clone(); + return prob; + } catch (CloneNotSupportedException e) { + return this; + } + } + + protected void checkSet() { + if (frozen) + throw new IllegalStateException("Object is unmodifieble"); //$NON-NLS-1$ + } + + /** + * @param b + */ + protected void setFrozen(boolean b) { + this.frozen = b; + } + + /** + * @return + */ + protected boolean isFrozen() { + return frozen; + } + + /** + * @param problemKey + */ + protected void notifyChanged(String key) { + if (getProfile() instanceof ProblemProfile) { + ((ProblemProfile) getProfile()).fireProfileChangeEvent(null, key, null, this); + } + } +} diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemProfile.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemProfile.java index 6a696d1c550..00b132fb874 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemProfile.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemProfile.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Alena Laskavaia + * Copyright (c) 2009, 2010 Alena Laskavaia * 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 @@ -16,13 +16,24 @@ import java.util.Collection; import org.eclipse.cdt.codan.core.model.IProblem; import org.eclipse.cdt.codan.core.model.IProblemCategory; import org.eclipse.cdt.codan.core.model.IProblemProfile; +import org.eclipse.cdt.codan.core.model.IProblemProfileChangeListener; +import org.eclipse.cdt.codan.core.model.ProblemProfileChangeEvent; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.SafeRunner; /** * @author Alena * */ public class ProblemProfile implements IProblemProfile, Cloneable { - private IProblemCategory rootCategory = new CodanProblemCategory("root", "root"); //$NON-NLS-1$ //$NON-NLS-2$ + private CodanProblemCategory rootCategory; + + public ProblemProfile() { + rootCategory = new CodanProblemCategory("root", "root"); //$NON-NLS-1$ //$NON-NLS-2$ + rootCategory.setProfile(this); + } /* * (non-Javadoc) @@ -85,7 +96,12 @@ public class ProblemProfile implements IProblemProfile, Cloneable { public Object clone() { try { ProblemProfile clone = (ProblemProfile) super.clone(); - clone.rootCategory = (IProblemCategory) ((CodanProblemCategory) this.rootCategory).clone(); + clone.rootCategory = (CodanProblemCategory) this.rootCategory.clone(); + CodanProblemCategory cce = clone.rootCategory; + boolean fro = cce.isFrozen(); + cce.setFrozen(false); + cce.setProfile(this); + cce.setFrozen(fro); return clone; } catch (CloneNotSupportedException e) { return this; @@ -99,4 +115,66 @@ public class ProblemProfile implements IProblemProfile, Cloneable { public void addCategory(IProblemCategory category, IProblemCategory parent) { ((CodanProblemCategory) parent).addChild(category); } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.codan.core.model.IProblemElement#getProfile() + */ + public IProblemProfile getProfile() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.codan.core.model.IProblemElement#getParentCategory() + */ + public IProblemCategory getParentCategory() { + return getRoot(); + } + private ListenerList preferenceChangeListeners; + + /** + * @param listener + */ + public void addProfileChangeListener(IProblemProfileChangeListener listener) { + if (preferenceChangeListeners == null) + preferenceChangeListeners = new ListenerList(); + preferenceChangeListeners.add(listener); + } + + /** + * @param listener + */ + public void removeProfileChangeListener(IProblemProfileChangeListener listener) { + if (preferenceChangeListeners == null) + return; + preferenceChangeListeners.remove(listener); + if (preferenceChangeListeners.size() == 0) + preferenceChangeListeners = null; + } + + /* + * Convenience method for notifying preference change listeners. + */ + protected void fireProfileChangeEvent(IResource resource, String key, Object oldValue, Object newValue) { + if (preferenceChangeListeners == null) + return; + Object[] listeners = preferenceChangeListeners.getListeners(); + final ProblemProfileChangeEvent event = new ProblemProfileChangeEvent(this, resource, key, oldValue, newValue); + for (int i = 0; i < listeners.length; i++) { + final IProblemProfileChangeListener listener = (IProblemProfileChangeListener) listeners[i]; + ISafeRunnable job = new ISafeRunnable() { + public void handleException(Throwable exception) { + // already logged in Platform#run() + } + + public void run() throws Exception { + listener.profileChange(event); + } + }; + SafeRunner.run(job); + } + } }