blob: 35cfa898fbd4f7ca556d969a318430be70217796 [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.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.filesystem.provider.FileStore;
import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.ResourceTreeNode;
import org.eclipse.core.resources.semantic.ISemanticProperties;
import org.eclipse.core.resources.semantic.SemanticResourceException;
import org.eclipse.core.resources.semantic.SemanticResourceStatusCode;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
/**
* The {@link ISemanticProperties} implementation.
*
*/
public abstract class SemanticProperties extends FileStore implements ISemanticProperties {
protected ResourceTreeNode node;
protected final SemanticFileSystem fs;
SemanticProperties(SemanticFileSystem fs, ResourceTreeNode node) {
this.fs = fs;
this.node = node;
}
private IPath getPathForTrace() {
try {
return this.fs.getPathForNode(this.node);
} catch (RuntimeException rte) {
// $JL-EXC$
return new Path(this.node.getName());
}
}
/**
* @throws CoreException
*/
public Map<QualifiedName, String> getPersistentProperties() throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
}
checkAccessible();
Map<QualifiedName, String> result = new HashMap<QualifiedName, String>();
try {
this.fs.lockForRead();
HashMap<String, String> atts = this.node.getPersistentProperties();
if (atts == null) {
return result;
}
for (Map.Entry<String, String> entry : atts.entrySet()) {
String qualifier;
String localName;
int index = entry.getKey().indexOf('^');
if (index > 0) {
qualifier = entry.getKey().substring(0, index);
localName = entry.getKey().substring(index + 1);
} else {
qualifier = null;
localName = entry.getKey();
}
result.put(new QualifiedName(qualifier, localName), entry.getValue());
}
return result;
} finally {
this.fs.unlockForRead();
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), result);
}
}
}
/**
* @throws CoreException
*/
public String getPersistentProperty(QualifiedName key) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(),
new Object[] {getPathForTrace().toString(), key});
}
String result = null;
try {
this.fs.lockForRead();
HashMap<String, String> nodeProps = this.node.getPersistentProperties();
if (nodeProps == null) {
return result;
}
String keyString = Util.qualifiedNameToString(key);
result = nodeProps.get(keyString);
return result;
} finally {
this.fs.unlockForRead();
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), result);
}
}
}
public void setPersistentProperty(QualifiedName key, String value) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
}
checkAccessible();
Util.assertQualifiedNameValid(key);
String keyString = Util.qualifiedNameToString(key);
try {
this.fs.lockForWrite();
String oldValue = null;
HashMap<String, String> map = this.node.getPersistentProperties();
if (map == null) {
map = new HashMap<String, String>();
} else {
oldValue = map.get(keyString);
}
if (!isEqualValue(value, oldValue)) {
if (value != null) {
map.put(keyString, value);
} else {
map.remove(keyString);
}
this.node.setPersistentProperties(map);
this.notifyPersistentPropertySet(keyString, oldValue, value);
this.fs.requestFlush(false, this.node);
}
} finally {
this.fs.unlockForWrite();
}
}
public void updatePersistentProperties(Map<QualifiedName, String> propertiesToBeAddedOrUpdated,
List<QualifiedName> propertiesToBeDeleted) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
}
checkAccessible();
// check all keys to be added/updated
if (propertiesToBeAddedOrUpdated != null) {
for (QualifiedName key : propertiesToBeAddedOrUpdated.keySet()) {
Util.assertQualifiedNameValid(key);
}
}
try {
this.fs.lockForWrite();
boolean needsFlush = false;
HashMap<String, String> map = this.node.getPersistentProperties();
if (map == null) {
map = new HashMap<String, String>();
}
if (propertiesToBeDeleted != null) {
for (QualifiedName key : propertiesToBeDeleted) {
String keyString = Util.qualifiedNameToString(key);
if (map.get(keyString) != null) {
map.remove(keyString);
needsFlush = true;
}
}
}
if (propertiesToBeAddedOrUpdated != null) {
for (Entry<QualifiedName, String> entry : propertiesToBeAddedOrUpdated.entrySet()) {
String keyString = Util.qualifiedNameToString(entry.getKey());
String oldValue = null;
oldValue = map.get(keyString);
if (!isEqualValue(entry.getValue(), oldValue) && entry.getValue() != null) {
map.put(keyString, entry.getValue());
this.notifyPersistentPropertySet(keyString, oldValue, entry.getValue());
needsFlush = true;
}
}
}
if (needsFlush) {
this.node.setPersistentProperties(map);
this.fs.requestFlush(false, node);
}
} finally {
this.fs.unlockForWrite();
}
}
protected abstract void notifyPersistentPropertySet(String keyString, String oldValue, String newValue) throws CoreException;
/**
* @throws CoreException
*/
public void setSessionProperty(QualifiedName key, Object value) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
}
checkAccessible();
Util.assertQualifiedNameValid(key);
try {
this.fs.lockForWrite();
HashMap<QualifiedName, Object> map = this.node.getSessionProperties();
if (map == null) {
map = new HashMap<QualifiedName, Object>();
this.node.setSessionProperties(map);
}
if (value != null) {
map.put(key, value);
} else {
map.remove(key);
}
} finally {
this.fs.unlockForWrite();
}
}
/**
* @throws CoreException
*/
public Map<QualifiedName, Object> getSessionProperties() throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
}
checkAccessible();
Map<QualifiedName, Object> result = new HashMap<QualifiedName, Object>();
try {
this.fs.lockForRead();
HashMap<QualifiedName, Object> atts = this.node.getSessionProperties();
if (atts == null) {
return result;
}
// we copy the map here (QualifiedName is immutable)
for (Map.Entry<QualifiedName, Object> entry : atts.entrySet()) {
result.put(entry.getKey(), entry.getValue());
}
return result;
} finally {
this.fs.unlockForRead();
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), result);
}
}
}
/**
* @throws CoreException
*/
public Object getSessionProperty(QualifiedName key) throws CoreException {
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(),
new Object[] {getPathForTrace().toString(), key});
}
Object result = null;
try {
this.fs.lockForRead();
HashMap<QualifiedName, Object> nodeProps = this.node.getSessionProperties();
if (nodeProps == null) {
return result;
}
result = nodeProps.get(key);
return result;
} finally {
this.fs.unlockForRead();
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), result);
}
}
}
/**
* Similar to
* <code>org.eclipse.core.internal.resources.Resource#checkAccessible(int)</code>
* <p>
* The corresponding Resource method is called on:
* <ul>
* <li>Container.memebers()</li>
* <li>Container.setDefaultCharset()</li>
* <li>File.appendContents()</li>
* <li>File.create() (on the parent)</li>
* <li>File.getContentDescription()</li>
* <li>File.getContents()</li>
* <li>File.getEncoding()</li>
* <li>File.setCharset()</li>
* <li>File.setContents()</li>
* <li>Folder.create() (on the parent)</li>
* <li>Project.checkAccessible()</li>
* <li>Project.getDescription()</li>
* <li>Project.getNature()</li>
* <li>Project.getReferencedProjects()</li>
* <li>Project.hasNature</li>
* <li>Project.isNatureEnabled()</li>
* <li>Project.setDescription()</li>
* <li>Resource.accept()</li>
* <li>Resource.createLink()</li>
* <li>Resource.copy()</li>
* <li>Resource.move()</li>
* <li>Resource.createMarker()</li>
* <li>Resource.deleteMarkers()</li>
* <li>Resource.findMarkers()</li>
* <li>Resource.findMaxProblemSeverity()</li>
* <li>Resource.setDerived()</li>
* <li>Resource.setHidden()</li>
* <li>Resource.setTeamPrivateMember()</li>
* </ul>
*
* @throws CoreException
*/
protected void checkAccessible() throws CoreException {
checkAndJoinTreeIfAnotherEntryExists();
if (!this.node.isExists()) {
throw new SemanticResourceException(SemanticResourceStatusCode.NOT_ACCESSIBLE, getPathForTrace(),
Messages.SemanticProperties_StoreNotAccessible_XMSG);
}
}
protected void checkAndJoinTreeIfAnotherEntryExists() {
try {
this.fs.lockForRead();
if (!this.node.isExists()) {
ResourceTreeNode other = this.fs.getNodeByPath(this.node.getPath());
if (other.isExists()) {
this.node = other;
}
}
} finally {
this.fs.unlockForRead();
if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation());
}
}
}
private boolean isEqualValue(String value, String oldValue) {
if (value == null && oldValue == null) {
return true;
} else if (value != null && oldValue == null) {
return false;
} else if (value == null && oldValue != null) {
return false;
}
return value.equals(oldValue);
}
}