/******************************************************************************* * Copyright (c) 2000, 2010 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.jdt.internal.ui.workingsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetUpdater; import org.eclipse.jdt.core.ElementChangedEvent; import org.eclipse.jdt.core.IElementChangedListener; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaElementDelta; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; public class JavaWorkingSetUpdater implements IWorkingSetUpdater, IElementChangedListener { /** * DO NOT REMOVE, used in a product, see https://bugs.eclipse.org/297529 . * @deprecated As of 3.5, replaced by {@link IWorkingSetIDs#JAVA} */ public static final String ID= IWorkingSetIDs.JAVA; private List fWorkingSets; private static class WorkingSetDelta { private IWorkingSet fWorkingSet; private List fElements; private boolean fChanged; public WorkingSetDelta(IWorkingSet workingSet) { fWorkingSet= workingSet; fElements= new ArrayList(Arrays.asList(workingSet.getElements())); } public int indexOf(Object element) { return fElements.indexOf(element); } public void set(int index, Object element) { fElements.set(index, element); fChanged= true; } public void remove(int index) { if (fElements.remove(index) != null) { fChanged= true; } } public void process() { if (fChanged) { fWorkingSet.setElements((IAdaptable[])fElements.toArray(new IAdaptable[fElements.size()])); } } } public JavaWorkingSetUpdater() { fWorkingSets= new ArrayList(); JavaCore.addElementChangedListener(this); } /** * {@inheritDoc} */ public void add(IWorkingSet workingSet) { checkElementExistence(workingSet); synchronized (fWorkingSets) { fWorkingSets.add(workingSet); } } /** * {@inheritDoc} */ public boolean remove(IWorkingSet workingSet) { boolean result; synchronized(fWorkingSets) { result= fWorkingSets.remove(workingSet); } return result; } /** * {@inheritDoc} */ public boolean contains(IWorkingSet workingSet) { synchronized(fWorkingSets) { return fWorkingSets.contains(workingSet); } } /** * {@inheritDoc} */ public void dispose() { synchronized(fWorkingSets) { fWorkingSets.clear(); } JavaCore.removeElementChangedListener(this); } /** * {@inheritDoc} */ public void elementChanged(ElementChangedEvent event) { IWorkingSet[] workingSets; synchronized(fWorkingSets) { workingSets= (IWorkingSet[])fWorkingSets.toArray(new IWorkingSet[fWorkingSets.size()]); } for (int w= 0; w < workingSets.length; w++) { WorkingSetDelta workingSetDelta= new WorkingSetDelta(workingSets[w]); processJavaDelta(workingSetDelta, event.getDelta()); IResourceDelta[] resourceDeltas= event.getDelta().getResourceDeltas(); if (resourceDeltas != null) { for (int r= 0; r < resourceDeltas.length; r++) { processResourceDelta(workingSetDelta, resourceDeltas[r]); } } workingSetDelta.process(); } } private void processJavaDelta(WorkingSetDelta result, IJavaElementDelta delta) { IJavaElement jElement= delta.getElement(); int index= result.indexOf(jElement); int type= jElement.getElementType(); int kind= delta.getKind(); int flags= delta.getFlags(); if (type == IJavaElement.JAVA_PROJECT && kind == IJavaElementDelta.CHANGED) { if (index != -1 && (flags & IJavaElementDelta.F_CLOSED) != 0) { result.set(index, ((IJavaProject)jElement).getProject()); } else if ((flags & IJavaElementDelta.F_OPENED) != 0) { index= result.indexOf(((IJavaProject)jElement).getProject()); if (index != -1) result.set(index, jElement); } } if (index != -1) { if (kind == IJavaElementDelta.REMOVED) { if ((flags & IJavaElementDelta.F_MOVED_TO) != 0) { result.set(index, delta.getMovedToElement()); } else { result.remove(index); } } } IResourceDelta[] resourceDeltas= delta.getResourceDeltas(); if (resourceDeltas != null) { for (int i= 0; i < resourceDeltas.length; i++) { processResourceDelta(result, resourceDeltas[i]); } } IJavaElementDelta[] children= delta.getAffectedChildren(); for (int i= 0; i < children.length; i++) { processJavaDelta(result, children[i]); } } private void processResourceDelta(WorkingSetDelta result, IResourceDelta delta) { IResource resource= delta.getResource(); int type= resource.getType(); int index= result.indexOf(resource); int kind= delta.getKind(); int flags= delta.getFlags(); if (kind == IResourceDelta.CHANGED && type == IResource.PROJECT && index != -1) { if ((flags & IResourceDelta.OPEN) != 0) { result.set(index, resource); } } if (index != -1 && kind == IResourceDelta.REMOVED) { if ((flags & IResourceDelta.MOVED_TO) != 0) { result.set(index, ResourcesPlugin.getWorkspace().getRoot().findMember(delta.getMovedToPath())); } else { result.remove(index); } } // Don't dive into closed or opened projects if (projectGotClosedOrOpened(resource, kind, flags)) return; IResourceDelta[] children= delta.getAffectedChildren(); for (int i= 0; i < children.length; i++) { processResourceDelta(result, children[i]); } } private boolean projectGotClosedOrOpened(IResource resource, int kind, int flags) { return resource.getType() == IResource.PROJECT && kind == IResourceDelta.CHANGED && (flags & IResourceDelta.OPEN) != 0; } private void checkElementExistence(IWorkingSet workingSet) { List elements= new ArrayList(Arrays.asList(workingSet.getElements())); boolean changed= false; for (Iterator iter= elements.iterator(); iter.hasNext();) { IAdaptable element= (IAdaptable)iter.next(); boolean remove= false; if (element instanceof IJavaElement) { IJavaElement jElement= (IJavaElement)element; // If we have directly a project then remove it when it // doesn't exist anymore. However if we have a sub element // under a project only remove the element if the parent // project is open. Otherwise we would remove all elements // in closed projects. if (jElement instanceof IJavaProject) { remove= !jElement.exists(); } else { final IJavaProject javaProject= jElement.getJavaProject(); final boolean isProjectOpen= javaProject != null ? javaProject.getProject().isOpen() : true; remove= isProjectOpen && !jElement.exists(); } } else if (element instanceof IResource) { IResource resource= (IResource)element; // See comments above if (resource instanceof IProject) { remove= !resource.exists(); } else { IProject project= resource.getProject(); remove= (project != null ? project.isOpen() : true) && !resource.exists(); } } if (remove) { iter.remove(); changed= true; } } if (changed) { workingSet.setElements((IAdaptable[])elements.toArray(new IAdaptable[elements.size()])); } } }