blob: 8b277fd512517d26ff2391ca29e7ba71fb0c1389 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 SAP AG.
* 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:
* Eduard Bartsch (SAP AG) - initial API and implementation
* Mathias Kinzler (SAP AG) - initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.resources.semantic;
import java.net.URI;
import java.util.List;
import java.util.Map;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.internal.resources.semantic.team.DelegatingResourceRuleFactory;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceRuleFactory;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.semantic.ISemanticFileSystem;
import org.eclipse.core.resources.semantic.ISemanticResource;
import org.eclipse.core.resources.semantic.ISemanticResourceInfo;
import org.eclipse.core.resources.semantic.SemanticResourceException;
import org.eclipse.core.resources.semantic.SemanticResourceStatusCode;
import org.eclipse.core.resources.semantic.SyncDirection;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.RepositoryProvider;
/**
* The {@link ISemanticResource} base implementation.
*
*/
public abstract class SemanticResourceAdapterImpl implements ISemanticResource {
/**
* Used for rule checking
*
*/
protected enum RuleType {
CREATE, DELETE, MODIFY, VALIDATE_EDIT, REFRESH
}
private final IResource resource;
private final ISemanticFileSystem fs;
SemanticResourceAdapterImpl(IResource resource, ISemanticFileSystem fileSystem) {
this.resource = resource;
this.fs = fileSystem;
}
public IResource getAdaptedResource() {
return this.resource;
}
/**
*
* @return store instance
* @throws CoreException
* if store can not be determined
*/
protected ISemanticFileStoreInternal getOwnStore() throws CoreException {
// TODO trace
URI uri = this.resource.getLocationURI();
try {
IFileStore store = EFS.getStore(uri);
if (store instanceof ISemanticFileStoreInternal) {
return (ISemanticFileStoreInternal) store;
} else if (store.getFileSystem() == EFS.getNullFileSystem()) {
throw new SemanticResourceException(SemanticResourceStatusCode.STORE_NOT_FOUND, this.resource.getFullPath(),
Messages.SemanticResourceAdapterImpl_NullFile_XMSG);
} else {
// quite unlikely (the URI was changed on the resource, e.g. on
// a project or symbolic link)
throw new SemanticResourceException(SemanticResourceStatusCode.STORE_NOT_FOUND, this.resource.getFullPath(), NLS.bind(
Messages.SemanticResourceAdapterImpl_NoSemanticStore_XMSG, uri.toString()));
}
} catch (CoreException e) {
throw new SemanticResourceException(SemanticResourceStatusCode.STORE_NOT_FOUND, this.resource.getFullPath(), null, e);
}
}
/**
*
* @return store instance
* @throws CoreException
* if store can not be determined
*/
protected static ISemanticFileStoreInternal getStoreForResource(IResource someResource) throws CoreException {
// TODO trace
URI uri = someResource.getLocationURI();
try {
IFileStore store = EFS.getStore(uri);
if (store instanceof ISemanticFileStoreInternal) {
return (ISemanticFileStoreInternal) store;
} else if (store.getFileSystem() == EFS.getNullFileSystem()) {
throw new SemanticResourceException(SemanticResourceStatusCode.STORE_NOT_FOUND, someResource.getFullPath(),
Messages.SemanticResourceAdapterImpl_NullFile_XMSG);
} else {
// quite unlikely (the URI was changed on the resource, e.g. on
// a project or symbolic link)
throw new SemanticResourceException(SemanticResourceStatusCode.STORE_NOT_FOUND, someResource.getFullPath(), NLS.bind(
Messages.SemanticResourceAdapterImpl_NoSemanticStore_XMSG, uri.toString()));
}
} catch (CoreException e) {
throw new SemanticResourceException(SemanticResourceStatusCode.STORE_NOT_FOUND, someResource.getFullPath(), null, e);
}
}
protected ISchedulingRule checkCurrentRule(RuleType ruleType) throws CoreException {
Job job = Job.getJobManager().currentJob();
if (job != null) {
ISchedulingRule checkRule = getRuleForType(ruleType, this.resource);
return validateCurrentRule(job, checkRule);
}
throw new SemanticResourceException(SemanticResourceStatusCode.CALLED_OUTSIDE_OF_SCHEDULING_RULE, this.resource.getFullPath(),
Messages.SemanticResourceAdapterImpl_CalledOutsideRule_XMSG);
}
protected ISchedulingRule checkCurrentMoveRule(IResource destination) throws CoreException {
Job job = Job.getJobManager().currentJob();
if (job != null) {
ISchedulingRule checkRule = getMoveRule(this.resource, destination);
return validateCurrentRule(job, checkRule);
}
throw new SemanticResourceException(SemanticResourceStatusCode.CALLED_OUTSIDE_OF_SCHEDULING_RULE, this.resource.getFullPath(),
Messages.SemanticResourceAdapterImpl_CalledOutsideRule_XMSG);
}
ISchedulingRule getMoveRule(IResource source, IResource destination) throws SemanticResourceException {
IResourceRuleFactory rf = getResourceRuleFactory(source);
return rf.moveRule(source, destination);
}
private ISchedulingRule validateCurrentRule(Job job, ISchedulingRule checkRule) throws SemanticResourceException {
ISchedulingRule rule = job.getRule();
if (rule != null) {
if (!rule.contains(checkRule)) {
throw new SemanticResourceException(SemanticResourceStatusCode.LOCK_CONFLICT, this.resource.getFullPath(),
Messages.SemanticResourceAdapterImpl_OperationNotCoveredByRule_XMSG);
}
} else {
// TODO 0.1: we need to investigate again what to do when rule
// is null
if (SfsTraceLocation.CORE.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE.getLocation(), Messages.SemanticResourceAdapterImpl_JobNoRule_XMSG);
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE.getLocation());
}
}
return checkRule;
}
private IResourceRuleFactory getResourceRuleFactory(IResource source) throws SemanticResourceException {
// TODO 0.1: check life cycle issues with project close/delete
IProject project = source.getProject();
if (!project.isAccessible()) {
// project closed or deleted
throw new SemanticResourceException(SemanticResourceStatusCode.PROJECT_NOT_ACCESSIBLE, source.getFullPath(), NLS.bind(
Messages.SemanticResourceAdapterImpl_ProjectNotAccessible_XMSG, project.getName()));
}
IResourceRuleFactory rf;
if (source.isLinked()) {
// fallback to default factory
rf = source.getWorkspace().getRuleFactory();
} else {
// we obtain the "expected" rule from the content provider
RepositoryProvider provider = RepositoryProvider.getProvider(project, ISemanticFileSystem.SFS_REPOSITORY_PROVIDER);
if (provider != null) {
rf = provider.getRuleFactory();
} else {
if (source.getType() == IResource.PROJECT) {
rf = source.getWorkspace().getRuleFactory();
} else {
rf = new DelegatingResourceRuleFactory(this.fs);
}
}
}
return rf;
}
ISchedulingRule getRuleForType(RuleType ruleType, IResource actResource) throws SemanticResourceException {
if (actResource instanceof IWorkspaceRoot) {
return actResource;
}
IResourceRuleFactory rf = getResourceRuleFactory(actResource);
ISchedulingRule checkRule;
switch (ruleType) {
case DELETE :
checkRule = rf.deleteRule(actResource);
break;
case CREATE :
checkRule = rf.createRule(actResource);
break;
case MODIFY :
checkRule = rf.modifyRule(actResource);
break;
case REFRESH :
checkRule = rf.refreshRule(actResource);
break;
case VALIDATE_EDIT :
checkRule = rf.validateEditRule(new IResource[] {actResource});
break;
default :
throw new RuntimeException(Messages.SemanticResourceAdapterImpl_UnknownRuleType_XMSG);
}
return checkRule;
}
protected void refreshLocalIfNeeded(RuleType ruleType, ISchedulingRule rule, int options, IProgressMonitor monitor)
throws CoreException {
if ((options & ISemanticFileSystem.SUPPRESS_REFRESH) == 0) {
if (rule instanceof IResource) {
if (SfsTraceLocation.CORE.isActive()) {
SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE.getLocation());
}
((IResource) rule).refreshLocal(IResource.DEPTH_INFINITE, monitor);
return;
}
throw new SemanticResourceException(SemanticResourceStatusCode.AUTO_REFRESH, new Path(""), NLS.bind( //$NON-NLS-1$
Messages.SemanticResourceAdapterImpl_RuleNoResource_XMSG, ruleType.name()));
}
}
public void deleteRemotely(int options, IProgressMonitor monitor) throws CoreException {
checkCurrentRule(RuleType.DELETE);
ISemanticFileStoreInternal store = getOwnStore();
store.deleteRemotely(monitor);
refreshLocalIfNeeded(RuleType.DELETE, getRuleForType(RuleType.MODIFY, this.resource), options, monitor);
}
public void remove(int options, IProgressMonitor monitor) throws CoreException {
checkCurrentRule(RuleType.DELETE);
ISemanticFileStoreInternal store = getOwnStore();
if ((options & ISemanticFileSystem.FORCE_REMOVE) != 0) {
store.forceRemoveFromWorkspace(options, monitor);
} else {
store.removeFromWorkspace(monitor);
}
refreshLocalIfNeeded(RuleType.DELETE, getRuleForType(RuleType.MODIFY, this.resource), options, monitor);
}
public IStatus validateRemoteDelete(Object shell) {
try {
ISemanticFileStoreInternal store = getOwnStore();
return store.validateRemoteDelete(shell);
} catch (CoreException e) {
if (SfsTraceLocation.CORE.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE.getLocation(), e.getMessage(), e);
}
return e.getStatus();
}
}
public IStatus validateRemove(int options, IProgressMonitor monitor) {
try {
ISemanticFileStoreInternal store = getOwnStore();
return store.validateRemove(options, monitor);
} catch (CoreException e) {
if (SfsTraceLocation.CORE.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE.getLocation(), e.getMessage(), e);
}
return e.getStatus();
}
}
public void synchronizeContentWithRemote(SyncDirection direction, int options, IProgressMonitor monitor) throws CoreException {
checkCurrentRule(RuleType.REFRESH);
ISemanticFileStoreInternal store = getOwnStore();
store.synchronizeContentWithRemote(direction, monitor);
refreshLocalIfNeeded(RuleType.MODIFY, getRuleForType(RuleType.MODIFY, this.resource), options, monitor);
}
public ISemanticResourceInfo fetchResourceInfo(int options, IProgressMonitor monitor) throws CoreException {
ISemanticFileStoreInternal store = getOwnStore();
return store.fetchResourceInfo(options, monitor);
}
public String getContentProviderID() throws CoreException {
ISemanticFileStoreInternal store = getOwnStore();
return store.getContentProviderID();
}
public IStatus lockResource(int options, IProgressMonitor monitor) throws CoreException {
checkCurrentRule(RuleType.REFRESH);
ISemanticFileStoreInternal store = getOwnStore();
IStatus result = store.lockResource(monitor);
if (result.isOK()) {
refreshLocalIfNeeded(RuleType.MODIFY, getRuleForType(RuleType.MODIFY, this.resource), options, monitor);
}
return result;
}
public IStatus unlockResource(int options, IProgressMonitor monitor) throws CoreException {
checkCurrentRule(RuleType.REFRESH);
ISemanticFileStoreInternal store = getOwnStore();
IStatus result = store.unlockResource(monitor);
if (result.isOK()) {
refreshLocalIfNeeded(RuleType.MODIFY, getRuleForType(RuleType.MODIFY, this.resource), options, monitor);
}
return result;
}
public Map<QualifiedName, String> getPersistentProperties() throws CoreException {
ISemanticFileStoreInternal store = getOwnStore();
return store.getPersistentProperties();
}
public String getPersistentProperty(QualifiedName key) throws CoreException {
ISemanticFileStoreInternal store = getOwnStore();
return store.getPersistentProperty(key);
}
public Map<QualifiedName, Object> getSessionProperties() throws CoreException {
ISemanticFileStoreInternal store = getOwnStore();
return store.getSessionProperties();
}
public Object getSessionProperty(QualifiedName key) throws CoreException {
ISemanticFileStoreInternal store = getOwnStore();
return store.getSessionProperty(key);
}
public void setPersistentProperty(QualifiedName key, String value) throws CoreException {
checkCurrentRule(RuleType.MODIFY);
ISemanticFileStoreInternal store = getOwnStore();
store.setPersistentProperty(key, value);
}
public void updatePersistentProperties(Map<QualifiedName, String> propertiesToBeAddedOrUpdated,
List<QualifiedName> propertiesToBeDeleted) throws CoreException {
checkCurrentRule(RuleType.MODIFY);
ISemanticFileStoreInternal store = getOwnStore();
store.updatePersistentProperties(propertiesToBeAddedOrUpdated, propertiesToBeDeleted);
}
public void setSessionProperty(QualifiedName key, Object value) throws CoreException {
checkCurrentRule(RuleType.MODIFY);
ISemanticFileStoreInternal store = getOwnStore();
store.setSessionProperty(key, value);
}
public void setRemoteURI(URI uri, int options, IProgressMonitor monitor) throws CoreException {
checkCurrentRule(RuleType.REFRESH);
ISemanticFileStoreInternal store = getOwnStore();
store.setRemoteURI(uri, monitor);
refreshLocalIfNeeded(RuleType.MODIFY, getRuleForType(RuleType.MODIFY, this.resource), options, monitor);
}
}