package org.eclipse.core.internal.properties;
import java.io.File;
import java.util.*;
import org.eclipse.core.internal.localstore.Bucket;
import org.eclipse.core.internal.localstore.Bucket.Entry;
import org.eclipse.core.internal.localstore.BucketTree;
import org.eclipse.core.internal.properties.PropertyBucket.PropertyEntry;
import org.eclipse.core.internal.resources.*;
import org.eclipse.core.internal.utils.Messages;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.util.NLS;
public class PropertyManager2 implements IPropertyManager {
private static final int MAX_VALUE_SIZE = 2 * 1024;
class PropertyCopyVisitor extends Bucket.Visitor {
private List<PropertyEntry> changes = new ArrayList<>();
private IPath destination;
private IPath source;
public PropertyCopyVisitor(IPath source, IPath destination) {
this.source = source;
this.destination = destination;
}
@Override
public void afterSaving(Bucket bucket) throws CoreException {
saveChanges((PropertyBucket) bucket);
changes.clear();
}
private void saveChanges(PropertyBucket bucket) throws CoreException {
if (changes.isEmpty())
return;
Iterator<PropertyEntry> i = changes.iterator();
PropertyEntry entry = i.next();
tree.loadBucketFor(entry.getPath());
bucket.setProperties(entry);
while (i.hasNext())
bucket.setProperties(i.next());
bucket.save();
}
@Override
public int visit(Entry entry) {
PropertyEntry sourceEntry = (PropertyEntry) entry;
IPath destinationPath = destination.append(sourceEntry.getPath().removeFirstSegments(source.segmentCount()));
PropertyEntry destinationEntry = new PropertyEntry(destinationPath, sourceEntry);
changes.add(destinationEntry);
return CONTINUE;
}
}
BucketTree tree;
public PropertyManager2(Workspace workspace) {
this.tree = new BucketTree(workspace, new PropertyBucket());
}
@Override
public void closePropertyStore(IResource target) throws CoreException {
tree.getCurrent().save();
tree.getCurrent().flush();
}
@Override
public synchronized void copy(IResource source, IResource destination, int depth) throws CoreException {
copyProperties(source.getFullPath(), destination.getFullPath(), depth);
}
private void copyProperties(final IPath source, final IPath destination, int depth) throws CoreException {
Assert.isLegal(source.segmentCount() > 0);
Assert.isLegal(destination.segmentCount() > 0);
Assert.isLegal(source.segmentCount() > 1 || destination.segmentCount() == 1);
PropertyCopyVisitor copyVisitor = new PropertyCopyVisitor(source, destination);
tree.accept(copyVisitor, source, BucketTree.DEPTH_INFINITE);
}
@Override
public synchronized void deleteProperties(IResource target, int depth) throws CoreException {
tree.accept(new PropertyBucket.Visitor() {
@Override
public int visit(Entry entry) {
entry.delete();
return CONTINUE;
}
}, target.getFullPath(), depth == IResource.DEPTH_INFINITE ? BucketTree.DEPTH_INFINITE : depth);
}
@Override
public void deleteResource(IResource target) throws CoreException {
deleteProperties(target, IResource.DEPTH_INFINITE);
}
@Override
public synchronized Map<QualifiedName, String> getProperties(IResource target) throws CoreException {
final Map<QualifiedName, String> result = new HashMap<>();
tree.accept(new PropertyBucket.Visitor() {
@Override
public int visit(Entry entry) {
PropertyEntry propertyEntry = (PropertyEntry) entry;
int propertyCount = propertyEntry.getOccurrences();
for (int i = 0; i < propertyCount; i++)
result.put(propertyEntry.getPropertyName(i), propertyEntry.getPropertyValue(i));
return CONTINUE;
}
}, target.getFullPath(), BucketTree.DEPTH_ZERO);
return result;
}
@Override
public synchronized String getProperty(IResource target, QualifiedName name) throws CoreException {
if (name.getQualifier() == null) {
String message = Messages.properties_qualifierIsNull;
throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, target.getFullPath(), message, null);
}
IPath resourcePath = target.getFullPath();
PropertyBucket current = (PropertyBucket) tree.getCurrent();
tree.loadBucketFor(resourcePath);
return current.getProperty(resourcePath, name);
}
public BucketTree getTree() {
return tree;
}
public File getVersionFile() {
return tree.getVersionFile();
}
@Override
public synchronized void setProperty(IResource target, QualifiedName name, String value) throws CoreException {
Resource resource = (Resource) target;
ResourceInfo info = resource.getResourceInfo(false, false);
int flags = resource.getFlags(info);
resource.checkAccessible(flags);
if (value != null && value.length() > MAX_VALUE_SIZE) {
String message = NLS.bind(Messages.properties_valueTooLong, new Object[] {name.getQualifier(), name.getLocalName(), Integer.toString(MAX_VALUE_SIZE)});
throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, target.getFullPath(), message, null);
}
if (name.getQualifier() == null) {
String message = Messages.properties_qualifierIsNull;
throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, target.getFullPath(), message, null);
}
IPath resourcePath = target.getFullPath();
tree.loadBucketFor(resourcePath);
PropertyBucket current = (PropertyBucket) tree.getCurrent();
current.setProperty(resourcePath, name, value);
current.save();
}
@Override
public void shutdown(IProgressMonitor monitor) throws CoreException {
tree.close();
}
@Override
public void startup(IProgressMonitor monitor) {
}
}