blob: fdfc526a8a2cf9dae83b6b4dd3e475b4d6ec0904 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 Ecliptical Software Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Ecliptical Software Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.ds.internal.annotations;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.pde.core.plugin.ModelEntry;
import org.eclipse.pde.internal.core.IPluginModelListener;
import org.eclipse.pde.internal.core.PluginModelDelta;
import org.eclipse.pde.internal.core.PluginModelManager;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
@SuppressWarnings("restriction")
public class DSLibPluginModelListener implements IPluginModelListener {
private static DSLibPluginModelListener INSTANCE;
private final HashMap<IJavaProject, String> projects = new HashMap<>();
private final HashMap<String, Integer> counts = new HashMap<>();
private DSLibPluginModelListener() {
PluginModelManager.getInstance().addPluginModelListener(this);
}
private synchronized static DSLibPluginModelListener getInstance(boolean create) {
if (create && INSTANCE == null) {
INSTANCE = new DSLibPluginModelListener();
}
return INSTANCE;
}
private void decrementCount(String modelId) {
Integer oldCount = counts.get(modelId);
if (oldCount != null) {
if (oldCount.intValue() <= 1) {
counts.remove(modelId);
} else {
counts.put(modelId, oldCount.intValue() - 1);
}
}
}
public static void addProject(IJavaProject project, String modelId) {
DSLibPluginModelListener instance = getInstance(true);
synchronized (instance.projects) {
String oldModelId = instance.projects.put(project, modelId);
Integer count = instance.counts.getOrDefault(modelId, Integer.valueOf(0));
instance.counts.put(modelId, count.intValue() + 1);
if (oldModelId != null) {
instance.decrementCount(oldModelId);
}
}
}
public static void removeProject(IJavaProject project) {
DSLibPluginModelListener instance = getInstance(false);
if (instance != null) {
synchronized (instance.projects) {
String oldModelId = instance.projects.remove(project);
if (oldModelId != null) {
instance.decrementCount(oldModelId);
}
}
}
}
private boolean containsModel(ModelEntry[] entries, String id) {
for (ModelEntry entry : entries) {
if ("org.eclipse.pde.ds.lib".equals(entry.getId())) {
return true;
}
}
return false;
}
@Override
public void modelsChanged(PluginModelDelta delta) {
synchronized (projects) {
HashSet<String> modelIds = new HashSet<>(2);
for (String modelId : counts.keySet()) {
if (((delta.getKind() & PluginModelDelta.ADDED) != 0 && containsModel(delta.getAddedEntries(), modelId))
|| ((delta.getKind() & PluginModelDelta.CHANGED) != 0
&& containsModel(delta.getChangedEntries(), modelId))
|| ((delta.getKind() & PluginModelDelta.REMOVED) != 0
&& containsModel(delta.getRemovedEntries(), modelId))) {
modelIds.add(modelId);
}
}
ArrayList<IJavaProject> toUpdate = new ArrayList<>(projects.size());
if (!modelIds.isEmpty()) {
for (Map.Entry<IJavaProject, String> entry : projects.entrySet()) {
IJavaProject project = entry.getKey();
String modelId = entry.getValue();
if (modelIds.contains(modelId)) {
toUpdate.add(project);
}
}
}
if (!toUpdate.isEmpty()) {
requestClasspathUpdate(toUpdate);
}
}
}
private void requestClasspathUpdate(final Collection<IJavaProject> changedProjects) {
WorkspaceJob job = new WorkspaceJob(Messages.ProjectClasspathPreferenceChangeListener_jobName) {
@Override
public IStatus runInWorkspace(IProgressMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, Messages.DSAnnotationPreferenceListener_taskName,
changedProjects.size());
for (IJavaProject project : changedProjects) {
ProjectClasspathPreferenceChangeListener.updateClasspathContainer(project, progress.newChild(1));
}
return Status.OK_STATUS;
}
};
job.setSystem(true);
ISchedulingRule[] rules = changedProjects.stream().map(IJavaProject::getProject)
.toArray(size -> new ISchedulingRule[size]);
job.setRule(new MultiRule(rules));
Display display = Display.getCurrent();
if (display != null) {
PlatformUI.getWorkbench().getProgressService().showInDialog(display.getActiveShell(), job);
}
job.schedule();
}
public static void dispose() {
DSLibPluginModelListener instance = getInstance(false);
if (instance != null) {
PluginModelManager.getInstance().removePluginModelListener(instance);
}
}
}