| /******************************************************************************* |
| * Copyright (c) 2006, 2017 IBM Corporation 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 |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.dltk.ui.editor.saveparticipant; |
| |
| import java.util.ArrayList; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.ISafeRunnable; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.MultiStatus; |
| import org.eclipse.core.runtime.SafeRunner; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.dltk.core.DLTKLanguageManager; |
| import org.eclipse.dltk.core.IDLTKLanguageToolkit; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.internal.ui.IDLTKStatusConstants; |
| import org.eclipse.dltk.ui.DLTKUIPlugin; |
| import org.eclipse.dltk.utils.PriorityNatureExtensionManager; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.osgi.util.NLS; |
| |
| /** |
| * A registry for save participants. This registry manages |
| * {@link SaveParticipantDescriptor}s and keeps track of enabled save |
| * participants. |
| * <p> |
| * Save participants can be enabled and disabled on the Java > Editor > |
| * Save Participants preference page. Enabled save participants are notified |
| * through a call to |
| * {@link IPostSaveListener#saved(org.eclipse.jdt.core.ICompilationUnit, IRegion[], org.eclipse.core.runtime.IProgressMonitor)} |
| * whenever the {@link CompilationUnitDocumentProvider} saves a compilation unit |
| * that is in the workspace. |
| * </p> |
| * <p> |
| * An instance of this registry can be received through a call to |
| * {@link JavaPlugin#getSaveParticipantRegistry()}. |
| * </p> |
| * |
| * @since 3.0 |
| */ |
| public final class SaveParticipantRegistry |
| extends PriorityNatureExtensionManager<IPostSaveListener> { |
| |
| private static final IPostSaveListener[] EMPTY_ARRAY = new IPostSaveListener[0]; |
| |
| /** |
| * Creates a new instance. |
| */ |
| public SaveParticipantRegistry() { |
| super(DLTKUIPlugin.PLUGIN_ID + ".saveParticipants", |
| IPostSaveListener.class); |
| } |
| |
| @Override |
| protected boolean isValidElement(IConfigurationElement element) { |
| return "saveParticipant".equals(element.getName()); |
| } |
| |
| /** |
| * Returns an array of <code>IPostSaveListener</code> which are enabled in |
| * the given context. |
| * |
| * @param context |
| * the context from which to retrieve the settings from, not null |
| * @return the current enabled post save listeners according to the |
| * preferences |
| */ |
| public IPostSaveListener[] getEnabledPostSaveListeners( |
| ISourceModule module) { |
| ArrayList<IPostSaveListener> result = null; |
| final IDLTKLanguageToolkit toolkit = DLTKLanguageManager |
| .getLanguageToolkit(module); |
| if (toolkit != null) { |
| for (IPostSaveListener descriptor : getInstances( |
| toolkit.getNatureId())) { |
| if (descriptor.isEnabled(module)) { |
| if (result == null) { |
| result = new ArrayList<>(); |
| } |
| result.add(descriptor); |
| } |
| } |
| } |
| if (result == null) { |
| return EMPTY_ARRAY; |
| } else { |
| return result.toArray(new IPostSaveListener[result.size()]); |
| } |
| } |
| |
| @Override |
| protected IPostSaveListener[] createEmptyResult() { |
| return EMPTY_ARRAY; |
| } |
| |
| /** |
| * Tells whether one of the active post save listeners needs to be informed |
| * about the changed region in this save cycle. |
| * |
| * @param unit |
| * the unit which is about to be saved |
| * @return true if the change regions need do be determined |
| * @throws CoreException |
| * if something went wrong |
| */ |
| public static boolean isChangedRegionsRequired(final ISourceModule unit, |
| IPostSaveListener[] listeners) throws CoreException { |
| String message = SaveParticipantMessages.SaveParticipantRegistry_needsChangedRegionFailed; |
| final MultiStatus errorStatus = new MultiStatus(DLTKUIPlugin.PLUGIN_ID, |
| IDLTKStatusConstants.EDITOR_CHANGED_REGION_CALCULATION, message, |
| null); |
| |
| try { |
| final boolean result[] = new boolean[] { false }; |
| for (int i = 0; i < listeners.length; i++) { |
| final IPostSaveListener listener = listeners[i]; |
| SafeRunner.run(new ISafeRunnable() { |
| |
| @Override |
| public void run() throws Exception { |
| if (listener.needsChangedRegions(unit)) |
| result[0] = true; |
| } |
| |
| @Override |
| public void handleException(Throwable ex) { |
| String msg = NLS.bind( |
| "The save participant ''{0}'' caused an exception.", //$NON-NLS-1$ |
| listener.getId()); |
| DLTKUIPlugin.log(new Status(IStatus.ERROR, |
| DLTKUIPlugin.PLUGIN_ID, |
| IDLTKStatusConstants.EDITOR_POST_SAVE_NOTIFICATION, |
| msg, ex)); |
| |
| final String participantName = listener.getName(); |
| msg = NLS.bind( |
| SaveParticipantMessages.SaveParticipantRegistry_needsChangedRegionCausedException, |
| participantName, ex.toString()); |
| errorStatus.add(new Status(IStatus.ERROR, |
| DLTKUIPlugin.PLUGIN_ID, |
| IDLTKStatusConstants.EDITOR_CHANGED_REGION_CALCULATION, |
| msg, null)); |
| } |
| |
| }); |
| if (result[0]) |
| return true; |
| } |
| } finally { |
| if (!errorStatus.isOK()) |
| throw new CoreException(errorStatus); |
| } |
| |
| return false; |
| } |
| |
| } |