| /******************************************************************************* |
| * Copyright (c) 2000, 2008 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.core; |
| |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.jobs.ISchedulingRule; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.ModelException; |
| |
| /* |
| * Abstract class for operations that change the buildpath |
| */ |
| public abstract class ChangeBuildpathOperation extends ModelOperation { |
| |
| protected final boolean canChangeResources; |
| |
| public ChangeBuildpathOperation(IModelElement[] elements, |
| boolean canChangeResources) { |
| super(elements); |
| this.canChangeResources = canChangeResources; |
| } |
| |
| @Override |
| protected boolean canModifyRoots() { |
| // changing the buildpath can modify roots |
| return true; |
| } |
| |
| /* |
| * The resolved buildpath of the given project may have changed: - generate |
| * a delta - trigger indexing - update project references - create resolved |
| * buildpath markers |
| */ |
| protected void buildpathChanged(BuildpathChange change) |
| throws ModelException { |
| // reset the project's caches early since some clients rely on the |
| // project's caches being up-to-date when run inside an |
| // IWorkspaceRunnable |
| // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769#c5 ) |
| ScriptProject project = change.project; |
| project.resetCaches(); |
| |
| if (this.canChangeResources) { |
| // workaround for |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=177922 |
| if (isTopLevelOperation() |
| && !ResourcesPlugin.getWorkspace().isTreeLocked()) { |
| new BuildpathValidation(project).validate(); |
| } |
| |
| // delta, indexing and buildpath markers are going to be created by |
| // the delta processor |
| // while handling the .buildpath file change |
| |
| // however ensure project references are updated |
| // since some clients rely on the project references when run inside |
| // an IWorkspaceRunnable |
| new ProjectReferenceChange(project, change.oldResolvedBuildpath) |
| .updateProjectReferencesIfNecessary(); |
| |
| // and ensure that external folders are updated as well |
| new ExternalFolderChange(project, change.oldResolvedBuildpath) |
| .updateExternalFoldersIfNecessary(true/* |
| * refresh if external |
| * linked folder already |
| * exists |
| */, null); |
| |
| } else { |
| DeltaProcessingState state = ModelManager.getDeltaState(); |
| ModelElementDelta delta = new ModelElementDelta(getModel()); |
| int result = change |
| .generateDelta(delta, true/* add buildpath change */); |
| if ((result & BuildpathChange.HAS_DELTA) != 0) { |
| // create delta |
| addDelta(delta); |
| |
| // need to recompute root infos |
| state.rootsAreStale = true; |
| |
| // ensure indexes are updated |
| change.requestIndexing(); |
| |
| // ensure buildpath is validated on next build |
| state.addBuildpathValidation(project); |
| } |
| if ((result & BuildpathChange.HAS_PROJECT_CHANGE) != 0) { |
| // ensure project references are updated on next build |
| state.addProjectReferenceChange(project, |
| change.oldResolvedBuildpath); |
| } |
| if ((result & BuildpathChange.HAS_LIBRARY_CHANGE) != 0) { |
| // ensure external folders are updated on next build |
| state.addExternalFolderChange(project, |
| change.oldResolvedBuildpath); |
| } |
| } |
| } |
| |
| @Override |
| protected ISchedulingRule getSchedulingRule() { |
| return null; // no lock taken while changing buildpath |
| } |
| |
| @Override |
| public boolean isReadOnly() { |
| return !this.canChangeResources; |
| } |
| |
| } |