blob: 11484156aa3b9cd7fad3bdce3b1acbb0b3bf3f65 [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.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.provider.FileInfo;
import org.eclipse.core.filesystem.provider.FileStore;
import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.ResourceTreeNode;
import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.SemanticResourceDBFactory;
import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.TreeNodeType;
import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.TreeRoot;
import org.eclipse.core.internal.resources.semantic.util.ISemanticFileSystemLog;
import org.eclipse.core.resources.semantic.ISemanticFileSystem;
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.resources.semantic.spi.FileCacheServiceFactory;
import org.eclipse.core.resources.semantic.spi.ISemanticContentProvider;
import org.eclipse.core.resources.semantic.spi.ISemanticContentProviderFederation;
import org.eclipse.core.resources.semantic.spi.ISemanticContentProviderFederation2;
import org.eclipse.core.resources.semantic.spi.ISemanticContentProviderFederation2.FederatedProviderInfo;
import org.eclipse.core.resources.semantic.spi.ISemanticContentProviderLocal;
import org.eclipse.core.resources.semantic.spi.ISemanticContentProviderLocking;
import org.eclipse.core.resources.semantic.spi.ISemanticContentProviderREST;
import org.eclipse.core.resources.semantic.spi.ISemanticContentProviderRemote;
import org.eclipse.core.resources.semantic.spi.ISemanticFileStore;
import org.eclipse.core.resources.semantic.spi.ISemanticSpiResourceInfo;
import org.eclipse.core.resources.semantic.spi.MemoryCacheServiceFactory;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EList;
import org.eclipse.osgi.util.NLS;
/**
* The Semantic File Store implementation.
*
*/
public class SemanticFileStore extends SemanticProperties implements ISemanticFileStore, ISemanticFileStoreInternal {
// we can't use the class name, since we don't have it in the class loader
private final static String DEFAULT_CONTENT_PROVIDER_ID = "org.eclipse.core.resources.semantic.provider.DefaultContentProvider"; //$NON-NLS-1$
private final ISemanticFileSystemLog log;
private ISemanticContentProvider provider;
SemanticFileStore(SemanticFileSystem fs, ResourceTreeNode node) {
super(fs, node);
this.log = fs.getLog();
}
//
// IFileStore/FileStore
//
/**
* @throws CoreException
*/
@Override
public String[] childNames(int options, IProgressMonitor monitor) throws CoreException {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
EList<ResourceTreeNode> children = this.node.getChildren();
int counter = children.size();
String[] names = new String[counter];
int i = 0;
for (ResourceTreeNode resourceTreeNode : children) {
if (resourceTreeNode.isExists()) {
names[i] = resourceTreeNode.getName();
i++;
}
}
return names;
} finally {
this.fs.unlockForRead();
}
}
@Override
public IFileInfo fetchInfo(int options, IProgressMonitor monitor) throws CoreException {
FileInfo info;
this.checkAndJoinTreeIfAnotherEntryExists();
ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
boolean askContentProviderForReadonly = false;
boolean askContentProviderForTimestamp = false;
try {
this.fs.lockForRead();
info = new SemanticFileInfo();
info.setName(this.node.getName());
info.setExists(this.node.isExists());
TreeNodeType actType = this.node.getType();
info.setDirectory(actType.equals(TreeNodeType.FOLDER) || actType.equals(TreeNodeType.PROJECT));
if (info.isDirectory() || !this.node.isExists() || actType.equals(TreeNodeType.UNKNOWN)) {
// see IFileInfo.getLastModified()
info.setLastModified(EFS.NONE);
// false is the fall back for non-existing resources,
info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, false);
} else {
askContentProviderForTimestamp = true;
// local-only resources are always writable (for the time being)
if (!this.node.isLocalOnly()) {
askContentProviderForReadonly = true;
} else {
info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, false);
}
}
} finally {
this.fs.unlockForRead();
}
// communicate with content providers outside of our lock to avoid
// deadlocks
if (askContentProviderForReadonly) {
boolean readOnly = true;
try {
readOnly = effectiveProvider.fetchResourceInfo(this, ISemanticFileSystem.RESOURCE_INFO_READ_ONLY, monitor).isReadOnly();
} catch (CoreException e) {
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CONTENTPROVIDER.getLocation(), e.getMessage(), e);
}
}
info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, readOnly);
}
if (askContentProviderForTimestamp) {
try {
info.setLastModified(effectiveProvider.getResourceTimestamp(this, monitor));
} catch (CoreException e) {
// we don't want to crash everything if the resource is not
// accessible
info.setLastModified(EFS.NONE);
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CONTENTPROVIDER.getLocation(), e.getMessage(), e);
}
}
}
return info;
}
@Override
public void putInfo(IFileInfo info, int options, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
if (SfsTraceLocation.CORE.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE.getLocation(),
NLS.bind(Messages.SemanticFileStore_UpdateFileInfo_XMSG, getPath().toString()));
}
checkAccessible();
if ((options & EFS.SET_ATTRIBUTES) != 0) {
// we ignore Archive, Hidden, and Executable here
getEffectiveContentProvider().setReadOnly(this, info.getAttribute(EFS.ATTRIBUTE_READ_ONLY), monitor);
}
if ((options & EFS.SET_LAST_MODIFIED) != 0) {
long timestamp = info.getLastModified();
getEffectiveContentProvider().setResourceTimestamp(this, timestamp, monitor);
}
}
private static ISemanticContentProvider initProvider(String contentProviderID, ISemanticFileStore store) throws CoreException {
ISemanticContentProvider actProvider = SemanticFileSystemCore.getInstance().getContentProviderFactory(contentProviderID)
.createContentProvider();
actProvider.setRootStore(store);
((SemanticFileStore) store).setProvider(actProvider);
return actProvider;
}
public String getEffectiveContentProviderID() throws CoreException {
try {
this.fs.lockForWrite();
if (this.getContentProviderID() != null) {
return this.getContentProviderID();
}
ContentProviderData effectiveProviderData = getEffectiveContentProviderInternal();
if (effectiveProviderData.provider instanceof ISemanticContentProviderFederation2) {
IPath thisPath = this.getPath();
return findFederatedContentProvider(thisPath, this.fs, this.node, effectiveProviderData).providerID;
}
return effectiveProviderData.providerID;
} finally {
this.fs.unlockForWrite();
}
}
public ISemanticContentProvider getEffectiveContentProvider() throws CoreException {
try {
this.fs.lockForWrite();
// TODO 0.1: check if we can use more fine grained locks here
if (this.provider != null) {
return this.provider;
}
ContentProviderData effectiveProviderData = getEffectiveContentProviderInternal();
if (effectiveProviderData.provider instanceof ISemanticContentProviderFederation2) {
IPath thisPath = this.getPath();
return findFederatedContentProvider(thisPath, this.fs, this.node, effectiveProviderData).provider;
}
return effectiveProviderData.provider;
} finally {
this.fs.unlockForWrite();
}
}
private static ContentProviderData findFederatedContentProvider(IPath path, SemanticFileSystem fs, ResourceTreeNode node,
ContentProviderData parentProviderData) throws CoreException {
int relativePathLength = path.segmentCount() - parentProviderData.provider.getRootStore().getPath().segmentCount();
if (relativePathLength > 0) {
ISemanticContentProviderFederation2 federatingProvider = (ISemanticContentProviderFederation2) parentProviderData.provider;
FederatedProviderInfo info = federatingProvider.getFederatedProviderInfoForPath(path);
if (info != null) {
if (info.contentProviderID == null) {
throw new SemanticResourceException(SemanticResourceStatusCode.FEDERATION_EMPTY_FEDERATED_PROVIDER_ID, path, NLS.bind(
Messages.SemanticFileStore_FederatingContentProviderReturnedNull_XMSG, federatingProvider.getClass().getName(),
path.toString()));
}
if (info.rootNodePosition <= 0 || info.rootNodePosition > relativePathLength) {
throw new SemanticResourceException(SemanticResourceStatusCode.FEDERATION_INVALID_ROOT_NODE_POSITION, path, NLS.bind(
Messages.SemanticFileStore_FederatingContentProviderReturnedInvalidRootNodePosition_XMSG, federatingProvider
.getClass().getName(), path.toString()));
}
ResourceTreeNode parent = node;
for (int i = 0; i < (relativePathLength - info.rootNodePosition); i++) {
if (parent != null) {
parent = parent.getParent();
}
}
if (parent != null) {
parent.setDynamicContentProviderID(info.contentProviderID);
} else {
String pathString = path.removeLastSegments(relativePathLength - info.rootNodePosition).toString();
parent = fs.getNodeByPath(pathString);
}
ISemanticContentProvider nestedProvider = initProvider(info.contentProviderID, fs.getStore(parent));
ContentProviderData nestedProviderData = new ContentProviderData(nestedProvider, info.contentProviderID);
if (nestedProvider instanceof ISemanticContentProviderFederation2) {
return findFederatedContentProvider(path, fs, node, nestedProviderData);
}
return nestedProviderData;
}
}
return parentProviderData;
}
private static class ContentProviderData {
ContentProviderData(ISemanticContentProvider provider, String providerID) {
this.provider = provider;
this.providerID = providerID;
}
ISemanticContentProvider provider;
String providerID;
}
private ContentProviderData getEffectiveContentProviderInternal() throws CoreException {
ISemanticFileStore parentStore;
String parentContentProviderId = SemanticFileStore.DEFAULT_CONTENT_PROVIDER_ID;
ResourceTreeNode parent = null;
ResourceTreeNode cpRootParent;
this.checkAndJoinTreeIfAnotherEntryExists();
if (this.node.getTemplateID() != null) {
String contentProviderID = this.node.getTemplateID();
// TODO move outside of lock
initProvider(contentProviderID, this);
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), contentProviderID);
}
return new ContentProviderData(this.provider, contentProviderID);
}
if (this.node.getDynamicContentProviderID() != null) {
String contentProviderID = this.node.getDynamicContentProviderID();
// TODO move outside of lock
initProvider(contentProviderID, this);
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), contentProviderID);
}
return new ContentProviderData(this.provider, contentProviderID);
}
if (!this.node.isExists()) {
List<ResourceTreeNode> nodes = this.fs.getNodesByPath(this.node.getPath());
// go down to find a contentProviderID
cpRootParent = nodes.get(0);
int counter = 0;
// scan the existing part where CP IDs are already assigned
for (ResourceTreeNode resourceTreeNode : nodes) {
if (resourceTreeNode.isExists()) {
if (resourceTreeNode.getTemplateID() != null) {
parentContentProviderId = resourceTreeNode.getTemplateID();
cpRootParent = resourceTreeNode;
}
counter++;
} else {
break;
}
}
// construct the root parent
parentStore = this.fs.getStore(cpRootParent);
// TODO move outside of lock?
ISemanticContentProvider parentProvider = initProvider(parentContentProviderId, parentStore);
// scan through non existing part
for (int i = counter; i < nodes.size(); i++) {
ResourceTreeNode resourceTreeNode = nodes.get(i);
if (parentProvider instanceof ISemanticContentProviderFederation) {
String federatedContentProviderId = ((ISemanticContentProviderFederation) parentProvider)
.getFederatedProviderIDForPath(new Path(resourceTreeNode.getPath()));
if (federatedContentProviderId != null) {
parentContentProviderId = federatedContentProviderId;
cpRootParent = resourceTreeNode;
parentStore = this.fs.getStore(cpRootParent);
// TODO move outside of lock?
parentProvider = initProvider(parentContentProviderId, parentStore);
}
}
}
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), parentContentProviderId);
}
return new ContentProviderData(parentProvider, parentContentProviderId);
}
// walk up to find a contentProviderID
parent = this.node.getParent();
if (parent == null) {
// this is a root store with default content provider
ISemanticContentProvider parentProvider = initProvider(parentContentProviderId, this);
return new ContentProviderData(parentProvider, parentContentProviderId);
}
ResourceTreeNode oldParent = this.node;
while (parent != null) {
parentContentProviderId = parent.getTemplateID();
if (parentContentProviderId != null) {
break;
}
oldParent = parent;
parent = parent.getParent();
}
if (parentContentProviderId == null) {
parentContentProviderId = SemanticFileStore.DEFAULT_CONTENT_PROVIDER_ID;
parent = oldParent;
}
// construct the parent
parentStore = this.fs.getStore(parent);
// TODO move outside of lock?
// the first parent with a provider ID
ISemanticContentProvider parentProvider = initProvider(parentContentProviderId, parentStore);
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), parentContentProviderId);
}
return new ContentProviderData(parentProvider, parentContentProviderId);
}
@Override
public File toLocalFile(int options, IProgressMonitor monitor) throws CoreException {
// some tools are operating directly on the file system; this enables
// these tools
// for content providers that have a file system cache by delegating to
// this cache
// non-caching content providers can not support this
// TODO 0.1: think of a more generic solution
this.checkAndJoinTreeIfAnotherEntryExists();
if (options != EFS.CACHE && this.node.isExists()) {
ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (effectiveProvider instanceof ISemanticContentProviderLocal) {
return ((ISemanticContentProviderLocal) effectiveProvider).toLocalFile(this);
}
// TODO 0.1: check exception handling in tools, adjust error message
return null;
}
IFileStore store = new FileStore() {
@Override
public URI toURI() {
return SemanticFileStore.this.toURI();
}
@Override
public InputStream openInputStream(int options1, IProgressMonitor monitor1) throws CoreException {
return SemanticFileStore.this.openInputStream(options1, monitor1);
}
@Override
public IFileStore getParent() {
return SemanticFileStore.this.getParent();
}
@Override
public String getName() {
return SemanticFileStore.this.getName();
}
@Override
public IFileStore getChild(String name) {
return SemanticFileStore.this.getChild(name);
}
@Override
public IFileInfo fetchInfo(int options1, IProgressMonitor monitor1) throws CoreException {
IFileInfo info = SemanticFileStore.this.fetchInfo(options1, monitor1);
if (info != null && info.exists()) {
// clear the read-only flag in order to temporarily fix the
// bug 323833 on MacOS
if (info.getAttribute(EFS.ATTRIBUTE_READ_ONLY)) {
info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, false);
}
}
return info;
}
@Override
public String[] childNames(int options1, IProgressMonitor monitor1) throws CoreException {
return SemanticFileStore.this.childNames(options1, monitor1);
}
};
return store.toLocalFile(options, monitor);
}
@Override
public IFileStore getChild(String name) {
IFileStore store = findChild(name);
if (store != null) {
return store;
}
ISemanticContentProvider effectiveProvider;
try {
effectiveProvider = getEffectiveContentProvider();
} catch (CoreException ce) {
this.log.log(ce);
return EFS.getNullFileSystem().getStore(getPath().append(name));
}
// no child found, let's check whether child can be created
// TODO 0.1: concurrency we need to detect and handle broken parent
// hierarchy
// situations
// due to concurrency (e.g. parent was deleted in another thread)
// check if there is federation
String federatedContentProviderId = null;
if (effectiveProvider instanceof ISemanticContentProviderFederation) {
federatedContentProviderId = ((ISemanticContentProviderFederation) effectiveProvider).getFederatedProviderIDForPath(getPath()
.append(name));
}
ISemanticFileStore result;
try {
this.fs.lockForWrite();
this.checkAndJoinTreeIfAnotherEntryExists();
store = findChild(name);
if (store != null) {
return store;
}
IPath childPath = this.getPath().append(name);
ResourceTreeNode newnode = createLocalChildNode(name, childPath, federatedContentProviderId);
result = this.fs.getStore(newnode);
} finally {
this.fs.unlockForWrite();
}
if (result != null) {
// notify the content provider
effectiveProvider.onImplicitStoreCreate(result);
if (federatedContentProviderId != null) {
// federation
try {
result.getEffectiveContentProvider().onImplicitStoreCreate(result);
} catch (CoreException e) {
// $JL-EXC$ ignore and just trace
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CONTENTPROVIDER.getLocation(), e.getMessage(), e);
}
}
}
}
return result;
}
@Override
public String getName() {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
return this.node.getName();
} finally {
this.fs.unlockForRead();
}
}
@Override
public IFileStore getParent() {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
ResourceTreeNode parentNode = this.fs.getParentNode(this.node);
if (parentNode != null) {
return this.fs.getStore(parentNode);
}
return null;
} finally {
this.fs.unlockForRead();
}
}
@Override
public InputStream openInputStream(int options, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
checkAccessible();
try {
this.fs.lockForRead();
TreeNodeType type = this.node.getType();
if (type != TreeNodeType.FILE) {
throw new SemanticResourceException(SemanticResourceStatusCode.INVALID_RESOURCE_TYPE, getPath(),
Messages.SemanticFileStore_OpenInputOnlyOnFiles_XMSG);
}
} finally {
this.fs.unlockForRead();
}
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace()
.trace(SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_OpeningInputInfo_XMSG, effectiveProvider.getClass().getName(), getPath()
.toString()));
}
return effectiveProvider.openInputStream(this, monitor);
}
@Override
public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException {
// TODO 0.1: concurrency/race condition with IFile.getContent()
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.checkAndJoinTreeIfAnotherEntryExists();
try {
this.fs.lockForRead();
TreeNodeType type = this.node.getType();
if (type != TreeNodeType.FILE && type != TreeNodeType.UNKNOWN) {
throw new SemanticResourceException(SemanticResourceStatusCode.INVALID_RESOURCE_TYPE, getPath(),
Messages.SemanticFileStore_OpenOutputNotOnFolders_XMSG);
}
} finally {
this.fs.unlockForRead();
}
ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
boolean append = (options & EFS.APPEND) != 0;
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
String message;
if (append) {
message = NLS.bind(Messages.SemanticFileStore_AppendingInfo_XMSG, effectiveProvider.getClass().getName(), getPath()
.toString());
} else {
message = NLS.bind(Messages.SemanticFileStore_OpeningInfo_XMSG, effectiveProvider.getClass().getName(), getPath()
.toString());
}
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CONTENTPROVIDER.getLocation(), message);
}
ISemanticSpiResourceInfo info = effectiveProvider.fetchResourceInfo(this, ISemanticFileSystem.RESOURCE_INFO_READ_ONLY, monitor);
if (info.isReadOnly()) {
IStatus status = effectiveProvider.validateSave(this);
if (!status.isOK()) {
throw new CoreException(status);
}
}
int actOptions = ISemanticFileSystem.NONE;
if (append) {
actOptions = ISemanticFileSystem.CONTENT_APPEND;
}
OutputStream os = effectiveProvider.openOutputStream(this, actOptions, monitor);
try {
this.fs.lockForWrite();
boolean changeRequired = !this.node.isExists() || this.node.getType() != TreeNodeType.FILE;
if (changeRequired) {
this.fs.switchToExists(this.node, this.fs.getParentNode(this.node));
this.node.setType(TreeNodeType.FILE);
try {
this.fs.requestFlush(false, this.node);
} catch (CoreException e) {
Util.safeClose(os);
throw e;
}
}
} finally {
this.fs.unlockForWrite();
}
return os;
}
@Override
public URI toURI() {
try {
this.fs.lockForRead();
try {
return new URI(ISemanticFileSystem.SCHEME, null, null, -1, getPath().toString(), node.getQueryPart(), null);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
} finally {
this.fs.unlockForRead();
}
}
@Override
public SemanticFileSystem getFileSystem() {
return this.fs;
}
@Override
public IFileStore mkdir(int options, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE_VERBOSE.getLocation(),
NLS.bind(Messages.SemanticFileStore_MkDir_XMSG, getPath().toString()));
}
try {
this.fs.lockForWrite();
this.checkAndJoinTreeIfAnotherEntryExists();
ResourceTreeNode parent = this.fs.getParentNode(this.node);
ISemanticContentProvider parentProvider = null;
if ((options & EFS.SHALLOW) != 0) {
if (parent != null && !parent.isExists()) {
throw new SemanticResourceException(SemanticResourceStatusCode.RESOURCE_PARENT_DOESNT_EXIST, getPath(),
Messages.SemanticFileStore_ShallowMkDirFailed_XMSG);
} else if (parent != null) { // and exists
parentProvider = fs.getStore(parent).getEffectiveContentProvider();
} else { // parent == null
parentProvider = getEffectiveContentProvider();
}
} else {
if (parent != null && !parent.isExists()) {
parentProvider = this.fs.mkdir(parent, this.fs.getParentNode(parent));
} else if (parent != null) { // and exists
parentProvider = fs.getStore(parent).getEffectiveContentProvider();
} else { // parent == null
parentProvider = getEffectiveContentProvider();
}
}
this.fs.makeFolder(this.node, parent, parentProvider);
} finally {
this.fs.unlockForWrite();
}
return this;
}
//
// ISemantiFileStoreInternal
//
public boolean supportsMove(ISemanticFileStore targetParent, String targetName, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
checkAccessible();
if (targetParent.hasChild(targetName)) {
return false;
}
if (effectiveProvider.isMoveSupportedForStore(this, targetParent, targetName, monitor)) {
final ISemanticContentProvider targetProvider = targetParent.getEffectiveContentProvider();
if (targetProvider.isMoveSupportedForStore(this, targetParent, targetName, monitor)) {
return true;
}
}
return false;
}
public void moveTo(ISemanticFileStore targetParent, String targetName, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
final ISemanticContentProvider targetProvider = targetParent.getEffectiveContentProvider();
checkAccessible();
if (targetParent.hasChild(targetName)) {
IPath newPath = targetParent.getPath().append(targetName);
throw new SemanticResourceException(SemanticResourceStatusCode.RESOURCE_ALREADY_EXISTS, newPath, NLS.bind(
Messages.SemanticFileStore_ResourceWithPathExists_XMSG, newPath.toString()));
}
targetParent.mkdir(0, monitor);
effectiveProvider.detachMovingStore(this, targetParent, targetName, monitor);
try {
this.fs.lockForWrite();
checkAccessible();
((SemanticFileStore) targetParent).checkAccessible();
ResourceTreeNode currentParent = this.node.getParent();
this.node.setParent(((SemanticFileStore) targetParent).node);
this.node.setName(targetName);
this.fs.requestFlush(true, currentParent);
this.fs.requestFlush(true, ((SemanticFileStore) targetParent).node);
} finally {
this.fs.unlockForWrite();
}
targetProvider.attachMovingStore(this, targetParent, targetName, monitor);
}
public void createFileRemotely(String name, InputStream source, Object context, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.mkdir(EFS.NONE, monitor);
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_CreateFileRemote_XMSG, name, effectiveProvider.getClass().getName(),
getPath().toString()));
}
if (effectiveProvider instanceof ISemanticContentProviderRemote) {
((ISemanticContentProviderRemote) effectiveProvider).createFileRemotely(this, name, source, context, monitor);
} else {
throw new SemanticResourceException(SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, getPath(), NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderRemote.class.getName()));
}
}
public ISemanticFileStoreInternal createResourceRemotely(String name, Object context, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.mkdir(EFS.NONE, monitor);
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_CreateResourceRemtoe_XMSG, name,
effectiveProvider.getClass().getName(), getPath().toString()));
}
if (effectiveProvider instanceof ISemanticContentProviderRemote) {
((ISemanticContentProviderRemote) effectiveProvider).createResourceRemotely(this, name, context, monitor);
} else {
throw new SemanticResourceException(SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, getPath(), NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderRemote.class.getName()));
}
return findChild(name);
}
public void addFileFromRemote(String name, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.mkdir(EFS.NONE, monitor);
ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_AddFileRemote_XMSG, name, effectiveProvider.getClass().getName(),
getPath().toString()));
}
// delegate to content provider
effectiveProvider.addResource(this, name, ResourceType.FILE_TYPE, monitor);
}
public void addFileFromRemoteByURI(String name, URI uri, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.mkdir(EFS.NONE, monitor);
ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
// delegate to content provider
if (effectiveProvider instanceof ISemanticContentProviderREST) {
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_AddFileRemoteURI_XMSG, name, uri.toString(), effectiveProvider
.getClass().getName(), getPath().toString()));
}
((ISemanticContentProviderREST) effectiveProvider).addFileFromRemoteByURI(this, name, uri, monitor);
} else {
throw new SemanticResourceException(SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, getPath(), NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderREST.class.getName()));
}
}
public void addFolderFromRemoteByURI(String name, URI uri, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.mkdir(EFS.NONE, monitor);
ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
// delegate to content provider
if (effectiveProvider instanceof ISemanticContentProviderREST) {
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_AddFileRemoteURI_XMSG, name, uri.toString(), effectiveProvider
.getClass().getName(), getPath().toString()));
}
((ISemanticContentProviderREST) effectiveProvider).addFolderFromRemoteByURI(this, name, uri, monitor);
} else {
throw new SemanticResourceException(SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, getPath(), NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderREST.class.getName()));
}
}
public void addFolderFromRemote(String name, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.mkdir(EFS.NONE, monitor);
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_AddFolderRemote_XMSG, name, effectiveProvider.getClass().getName(),
getPath().toString()));
}
// delegate to content provider
effectiveProvider.addResource(this, name, ResourceType.FOLDER_TYPE, monitor);
}
public ISemanticFileStoreInternal addResourceFromRemote(String name, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.mkdir(EFS.NONE, monitor);
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_AddResourceRemote_XMSG, name, effectiveProvider.getClass().getName(),
getPath().toString()));
}
// delegate to content provider
effectiveProvider.addResource(this, name, ResourceType.UNKNOWN_TYPE, monitor);
return findChild(name);
}
public void addResource(String name, boolean asFolder, String contentProviderID, Map<QualifiedName, String> properties,
IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.mkdir(EFS.NONE, monitor);
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (effectiveProvider instanceof ISemanticContentProviderFederation) {
((ISemanticContentProviderFederation) effectiveProvider).addResource(this, name, asFolder ? ResourceType.FOLDER_TYPE
: ResourceType.FILE_TYPE, contentProviderID, properties);
} else {
throw new SemanticResourceException(SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, getPath(), NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderFederation.class.getName()));
}
}
@Override
public void delete(int options, IProgressMonitor monitor) throws CoreException {
// this will be called instead of delete hook if no team provider is
// found
// or if resource is marked as derived
// TODO 0.1: review this behavior e.g. with respect to linked resources
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
removeFromWorkspace(monitor);
}
public void deleteRemotely(IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
this.checkAndJoinTreeIfAnotherEntryExists();
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_DeleteResourceRemote_XMSG, getPath().toString(), effectiveProvider.getClass()
.getName()));
}
if (effectiveProvider instanceof ISemanticContentProviderRemote) {
((ISemanticContentProviderRemote) effectiveProvider).deleteRemotely(this, monitor);
} else {
throw new SemanticResourceException(SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, getPath(), NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderRemote.class.getName()));
}
}
public void removeFromWorkspace(IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_RemoveResourceRemote_XMSG, getPath().toString(), effectiveProvider.getClass()
.getName()));
}
checkAccessible();
effectiveProvider.removeResource(this, monitor);
}
public void forceRemoveFromWorkspace(int options, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
checkAccessible();
new FileCacheServiceFactory().getCacheService().removeContentRecursive(getPath(), monitor);
new MemoryCacheServiceFactory().getCacheService().removeContentRecursive(getPath(), monitor);
this.remove(monitor);
}
public void forceRemove(int options, IProgressMonitor monitor) throws CoreException {
forceRemoveFromWorkspace(options, monitor);
}
public void synchronizeContentWithRemote(SyncDirection direction, IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_SynchContent_XMSG, effectiveProvider.getClass().getName(), getPath().toString()));
}
checkAccessible();
MultiStatus status = new MultiStatus(SemanticResourcesPlugin.PLUGIN_ID, IStatus.OK, NLS.bind(
Messages.SemanticFileStore_SyncContent_XGRP, getPath().toString()), null);
effectiveProvider.synchronizeContentWithRemote(this, direction, monitor, status);
if (!status.isOK()) {
throw new CoreException(status);
}
}
public void setRemoteURI(URI uri, IProgressMonitor monitor) throws CoreException {
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
checkAccessible();
// delegate to content provider
if (effectiveProvider instanceof ISemanticContentProviderREST) {
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_SettingURI_XMSG, uri.toString(), effectiveProvider.getClass()
.getName(), getPath().toString()));
}
((ISemanticContentProviderREST) effectiveProvider).setURIString(this, uri, monitor);
} else {
throw new SemanticResourceException(SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, getPath(), NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderREST.class.getName()));
}
}
public void revertChanges(IProgressMonitor monitor) throws CoreException {
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_Revert_XMSG, getPath().toString(), effectiveProvider.getClass().getName()));
}
checkAccessible();
effectiveProvider.revertChanges(this, monitor);
}
public IStatus lockResource(IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_Locking_XMSG, getPath().toString(), effectiveProvider.getClass().getName()));
}
checkAccessible();
if (effectiveProvider instanceof ISemanticContentProviderLocking) {
return ((ISemanticContentProviderLocking) effectiveProvider).lockResource(this, monitor);
}
return new Status(IStatus.ERROR, SemanticResourcesPlugin.PLUGIN_ID, NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderLocking.class.getName()));
}
public IStatus unlockResource(IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_Unlocking_XMSG, getPath().toString(), effectiveProvider.getClass().getName()));
}
checkAccessible();
if (effectiveProvider instanceof ISemanticContentProviderLocking) {
return ((ISemanticContentProviderLocking) effectiveProvider).unlockResource(this, monitor);
}
return new Status(IStatus.ERROR, SemanticResourcesPlugin.PLUGIN_ID, NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderLocking.class.getName()));
}
public IStatus validateRemoteCreate(String name, Object shell) {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
ISemanticContentProvider effectiveProvider;
try {
checkAccessible();
effectiveProvider = getEffectiveContentProvider();
} catch (CoreException ce) {
this.log.log(ce);
return ce.getStatus();
}
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_ValidateRemoteCreate_XMSG, name,
effectiveProvider.getClass().getName(), getPath().toString()));
}
if (effectiveProvider instanceof ISemanticContentProviderRemote) {
return ((ISemanticContentProviderRemote) effectiveProvider).validateRemoteCreate(this, name, shell);
}
return new Status(IStatus.ERROR, SemanticResourcesPlugin.PLUGIN_ID, NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderRemote.class.getName()));
}
public IStatus validateRemoteDelete(Object shell) {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
try {
checkAccessible();
} catch (CoreException e) {
return e.getStatus();
}
boolean canBeDeleted;
ISemanticContentProvider effectiveProvider;
try {
effectiveProvider = getEffectiveContentProvider();
} catch (CoreException e) {
this.log.log(e);
return e.getStatus();
}
try {
this.fs.lockForRead();
canBeDeleted = this.node.isExists();
} finally {
this.fs.unlockForRead();
}
if (canBeDeleted) {
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
MessageFormat.format(Messages.SemanticFileStore_ValidateRemoteDelete_XMSG, getPath().toString(), effectiveProvider
.getClass().getName()));
}
if (effectiveProvider instanceof ISemanticContentProviderRemote) {
return ((ISemanticContentProviderRemote) effectiveProvider).validateRemoteDelete(this, shell);
}
return new Status(IStatus.ERROR, SemanticResourcesPlugin.PLUGIN_ID, NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderRemote.class.getName()));
}
return new Status(IStatus.CANCEL, SemanticResourcesPlugin.PLUGIN_ID, null);
}
public IStatus validateRemove(int options, IProgressMonitor monitor) {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
try {
checkAccessible();
} catch (CoreException e) {
return e.getStatus();
}
boolean canBeDeleted;
ISemanticContentProvider effectiveProvider;
try {
effectiveProvider = getEffectiveContentProvider();
} catch (CoreException e) {
this.log.log(e);
return e.getStatus();
}
try {
this.fs.lockForRead();
canBeDeleted = this.node.isExists();
} finally {
this.fs.unlockForRead();
}
if (canBeDeleted) {
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_ValidateRemove_XMSG, getPath().toString(), effectiveProvider.getClass()
.getName()));
}
try {
return effectiveProvider.validateRemove(this, options, monitor);
} catch (CoreException e) {
this.log.log(e);
return e.getStatus();
}
}
return new Status(IStatus.CANCEL, SemanticResourcesPlugin.PLUGIN_ID, null);
}
public void addChildFolder(String name) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
if (SfsTraceLocation.CORE.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE.getLocation(),
NLS.bind(Messages.SemanticFileStore_AddChildFolder_XMSG, name, getPath().toString()));
}
try {
this.fs.lockForWrite();
checkAccessible();
checkChildExists(name);
createChildNode(name, true, null);
this.fs.requestFlush(false, this.node);
} finally {
this.fs.unlockForWrite();
}
}
public void addChildResource(String name, boolean asFolder, String contentProviderID, Map<QualifiedName, String> properties)
throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
if (SfsTraceLocation.CORE.isActive()) {
String message;
if (asFolder) {
message = NLS.bind(Messages.SemanticFileStore_AddContentProviderRootFolder_XMSG, name, getPath().toString());
} else {
message = NLS.bind(Messages.SemanticFileStore_AddContentProviderRootFile_XMSG, name, getPath().toString());
}
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE.getLocation(), message);
}
ResourceTreeNode child;
try {
this.fs.lockForWrite();
checkAccessible();
checkChildExists(name);
child = createChildNode(name, asFolder, contentProviderID);
HashMap<String, String> propsMap = new HashMap<String, String>();
if (properties != null && !properties.isEmpty()) {
for (Map.Entry<QualifiedName, String> entry : properties.entrySet()) {
propsMap.put(Util.qualifiedNameToString(entry.getKey()), entry.getValue());
}
child.setPersistentProperties(propsMap);
} else {
// we don't use an empty map, but null
child.setPersistentProperties(null);
}
this.fs.requestFlush(false, this.node);
} finally {
this.fs.unlockForWrite();
}
if (contentProviderID != null) {
ISemanticFileStore store = this.fs.getStore(child);
store.getEffectiveContentProvider().onRootStoreCreate(store);
}
}
public void addChildFile(String name) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
if (SfsTraceLocation.CORE.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE.getLocation(),
NLS.bind(Messages.SemanticFileStore_AddChildFile_XMSG, name, getPath().toString()));
}
try {
this.fs.lockForWrite();
checkAccessible();
checkChildExists(name);
createChildNode(name, false, null);
this.fs.requestFlush(false, this.node);
} finally {
this.fs.unlockForWrite();
}
}
public void addLocalChildResource(String name, String contentProviderID) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
if (SfsTraceLocation.CORE.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE.getLocation(),
NLS.bind(Messages.SemanticFileStore_AddLocalChild_XMSG, name, getPath().toString()));
}
try {
this.fs.lockForWrite();
checkAccessible();
checkChildExists(name);
createLocalChildNode(name, this.getPath().append(name), contentProviderID);
this.fs.requestFlush(false, this.node);
} finally {
this.fs.unlockForWrite();
}
}
public boolean hasResource(String name) {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
EList<ResourceTreeNode> children = this.node.getChildren();
for (ResourceTreeNode resourceTreeNode : children) {
if (resourceTreeNode.getName().equals(name)) {
return resourceTreeNode.isExists();
}
}
return false;
} finally {
this.fs.unlockForRead();
}
}
public boolean hasChild(String name) {
return hasResource(name);
}
public String getContentProviderID() {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
return this.node.getTemplateID();
} finally {
this.fs.unlockForRead();
}
}
public URI getRemoteURI() throws CoreException {
checkAccessible();
final ISemanticContentProvider effectiveProvider = getEffectiveContentProvider();
if (effectiveProvider instanceof ISemanticContentProviderREST) {
try {
String uriString = ((ISemanticContentProviderREST) effectiveProvider).getURIString(this);
return new URI(uriString);
} catch (URISyntaxException e) {
throw new SemanticResourceException(SemanticResourceStatusCode.INVALID_URI_SYNTAX, getPath(), NLS.bind(
Messages.SemanticFileStore_InvalidURISyntax_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderREST.class.getName()));
}
}
throw new SemanticResourceException(SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, getPath(), NLS.bind(
Messages.SemanticFileStore_IntefaceNotImplemented_XMSG, effectiveProvider.getClass().getName(),
ISemanticContentProviderREST.class.getName()));
}
public boolean isExists() {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
return this.node.isExists();
} finally {
this.fs.unlockForRead();
}
}
public boolean isLocalOnly() {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
return this.node.isLocalOnly();
} finally {
this.fs.unlockForRead();
}
}
public void setLocalOnly(boolean isLocalOnly) {
try {
this.fs.lockForWrite();
this.checkAndJoinTreeIfAnotherEntryExists();
this.node.setLocalOnly(isLocalOnly);
} finally {
this.fs.unlockForWrite();
}
}
//
// private section
//
/**
* @param name
*/
private SemanticFileStore findChild(String name) {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
EList<ResourceTreeNode> children = this.node.getChildren();
for (ResourceTreeNode resourceTreeNode : children) {
if (resourceTreeNode.getName().equals(name)) {
return (SemanticFileStore) this.fs.getStore(resourceTreeNode);
}
}
} finally {
this.fs.unlockForRead();
}
return null;
}
private ResourceTreeNode createChildNode(String name, boolean isFolder, String contentProviderID) {
// all callers have a lock, so we don't lock here
ResourceTreeNode child = SemanticResourceDBFactory.eINSTANCE.createResourceTreeNode();
child.setName(name);
child.setTemplateID(contentProviderID);
if (isFolder) {
child.setType(TreeNodeType.FOLDER);
// folders are always local-only
child.setLocalOnly(true);
} else {
child.setType(TreeNodeType.FILE);
child.setLocalOnly(false);
}
child.setExists(true);
child.setParent(this.node);
return child;
}
private ResourceTreeNode createLocalChildNode(String name, IPath childPath, String contentProviderID) {
// all callers have a lock, so we don't lock here
ResourceTreeNode child = SemanticResourceDBFactory.eINSTANCE.createResourceTreeNode();
child.setName(name);
child.setTemplateID(contentProviderID);
child.setType(TreeNodeType.UNKNOWN);
child.setExists(false); // needed to comply with resource creation
// behavior
child.setPath(childPath.toString());
child.setLocalOnly(true);
return child;
}
/*
* private ResourceTreeNode createPhantomNode(String name, boolean
* isDirectory, URI uri) { ResourceTreeNode child =
* SemanticResourceDBFactory.eINSTANCE.createResourceTreeNode();
*
* child.setName(name); child.setIsDirectory(isDirectory);
* child.setExists(false); child.setPhantom(true); child.setReadOnly(false);
* child.setParent(node); child.setLastModified(System.currentTimeMillis());
*
* if ( uri != null ) { child.setRemoteURI(uri.toString()); } return child;
* }
*/
/**
* throws exception if child exists
*/
private void checkChildExists(String name) throws CoreException {
// all callers have obtained a lock, so we don't lock here
EList<ResourceTreeNode> children = this.node.getChildren();
for (ResourceTreeNode resourceTreeNode : children) {
if (resourceTreeNode.getName().equals(name)) {
if (resourceTreeNode.isExists()) {
IPath newPath = getPath().append(name);
throw new SemanticResourceException(SemanticResourceStatusCode.RESOURCE_ALREADY_EXISTS, newPath, NLS.bind(
Messages.SemanticFileStore_ResourceWithPathExists_XMSG, newPath.toString()));
}
}
}
}
private static void cleanupNodeAndChildren(ResourceTreeNode node, IPath path) {
EList<ResourceTreeNode> children = node.getChildren();
for (ResourceTreeNode resourceTreeNode : children) {
cleanupNodeAndChildren(resourceTreeNode, path.append(resourceTreeNode.getName()));
}
// keep the last path so that getPath returns something meaningful after
// remove
node.setPath(path.toString());
node.setExists(false);
node.setPersistentProperties(null);
node.setSessionProperties(null);
children.clear();
}
public IStatus validateEdit(Object shell) {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
try {
checkAccessible();
} catch (CoreException e) {
return e.getStatus();
}
boolean canBeEdited;
ISemanticContentProvider effectiveProvider;
try {
effectiveProvider = getEffectiveContentProvider();
} catch (CoreException e) {
this.log.log(e);
return e.getStatus();
}
try {
this.fs.lockForRead();
// exist could be false if node was created, but no content was
// written yet
canBeEdited = this.node.isExists() && this.node.getType().equals(TreeNodeType.FILE);
} finally {
this.fs.unlockForRead();
}
if (canBeEdited) {
boolean readOnly;
try {
readOnly = effectiveProvider.fetchResourceInfo(this, ISemanticFileSystem.RESOURCE_INFO_READ_ONLY, null).isReadOnly();
} catch (CoreException e) {
this.log.log(e);
return e.getStatus();
}
if (readOnly) {
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_ValidateEdit_XMSG, effectiveProvider.getClass().getName(), getPath()
.toString()));
}
return effectiveProvider.validateEdit(new ISemanticFileStore[] {this}, shell);
}
// already checked out
return new Status(IStatus.OK, SemanticResourcesPlugin.PLUGIN_ID, null);
}
return new Status(IStatus.CANCEL, SemanticResourcesPlugin.PLUGIN_ID, null);
}
public IStatus validateSave() {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
try {
checkAccessible();
} catch (CoreException e) {
return e.getStatus();
}
boolean canBeSaved;
ISemanticContentProvider effectiveProvider;
try {
effectiveProvider = getEffectiveContentProvider();
} catch (CoreException e) {
this.log.log(e);
return e.getStatus();
}
try {
this.fs.lockForRead();
canBeSaved = this.node.isExists() && this.node.getType().equals(TreeNodeType.FILE);
} finally {
this.fs.unlockForRead();
}
if (canBeSaved) {
boolean readOnly;
try {
readOnly = effectiveProvider.fetchResourceInfo(this, ISemanticFileSystem.RESOURCE_INFO_READ_ONLY, null).isReadOnly();
} catch (CoreException e) {
this.log.log(e);
return e.getStatus();
}
if (!readOnly) {
if (SfsTraceLocation.CONTENTPROVIDER.isActive()) {
SfsTraceLocation.getTrace().trace(
SfsTraceLocation.CONTENTPROVIDER.getLocation(),
NLS.bind(Messages.SemanticFileStore_ValidateSave_XMSG, effectiveProvider.getClass().getName(), getPath()
.toString()));
}
return effectiveProvider.validateSave(this);
}
// not checked out
return new Status(IStatus.CANCEL, SemanticResourcesPlugin.PLUGIN_ID, NLS.bind(Messages.SemanticFileStore_NotWritable_XMSG,
getPath().toString()));
}
return new Status(IStatus.CANCEL, SemanticResourcesPlugin.PLUGIN_ID, null);
}
public IPath getPath() {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
return this.fs.getPathForNode(this.node);
} finally {
this.fs.unlockForRead();
}
}
public void remove(IProgressMonitor monitor) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceDumpStack(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
if (SfsTraceLocation.CORE.isActive()) {
SfsTraceLocation.getTrace().trace(SfsTraceLocation.CORE.getLocation(),
NLS.bind(Messages.SemanticFileStore_RemovingResource_XMSG, getPath().toString()));
}
try {
this.fs.lockForWrite();
this.checkAccessible();
SemanticFileStore.cleanupNodeAndChildren(node, getPath());
ResourceTreeNode topParent = this.fs.getHighestParent(this.node);
if (this.node instanceof TreeRoot) {
((TreeRoot) this.node).setParentDB(null);
} else {
this.node.setParent(null);
}
this.fs.requestFlush(false, topParent);
this.fs.requestURILocatorRebuild();
} finally {
this.fs.unlockForWrite();
}
}
public ISemanticResourceInfo fetchResourceInfo(int options, IProgressMonitor monitor) throws CoreException {
// checkAccessible();
ISemanticSpiResourceInfo providerInfo = getEffectiveContentProvider().fetchResourceInfo(this, options, getNotNullMonitor(monitor));
return new SemanticResourceInfo(options, providerInfo, isLocalOnly());
}
public int getType() {
try {
this.fs.lockForRead();
this.checkAndJoinTreeIfAnotherEntryExists();
return this.node.getType().getValue();
} finally {
this.fs.unlockForRead();
}
}
public ISemanticFileStoreInternal getChildResource(String name) {
// TODO checkAccessible()??
return findChild(name);
}
/**
* This is called during initialization of this class
*
* @param contentProvider
* the responsible content provider
*/
public void setProvider(ISemanticContentProvider contentProvider) {
this.provider = contentProvider;
}
/**
* @throws CoreException
*/
@Override
protected void notifyPersistentPropertySet(String keyString, String oldValue, String newValue) throws CoreException {
// nothing to do for now
}
public IPath[] findURI(URI uri, IProgressMonitor monitor) throws CoreException {
return this.fs.getURILocatorService(monitor).locateURI(uri, getPath());
}
public String getRemoteURIString() {
return node.getRemoteURI();
}
public void setRemoteURIString(String uriString) {
String oldValue = node.getRemoteURI();
node.setRemoteURI(uriString);
if (this.fs.getURILocator() != null) {
if ((oldValue == null && uriString != null) || (oldValue != null && !oldValue.equals(uriString))) {
IPath path = getPath();
if (oldValue != null) {
this.fs.getURILocator().removeURI(path, oldValue);
}
if (uriString != null) {
this.fs.getURILocator().addURI(path, uriString);
}
}
}
}
private IProgressMonitor getNotNullMonitor(IProgressMonitor monitor) {
if (monitor == null) {
return new NullProgressMonitor();
}
return monitor;
}
}