diff options
author | Andrew Ferguson | 2007-02-26 14:35:09 +0000 |
---|---|---|
committer | Andrew Ferguson | 2007-02-26 14:35:09 +0000 |
commit | 5099040937cf056d2b4f61df857cc041f0f5bd8c (patch) | |
tree | 897004ce9afb5079489d7b4978af1af96a79aad9 | |
parent | ac5293488b95db86544c144cb7025c288f7eca3c (diff) | |
download | org.eclipse.cdt-5099040937cf056d2b4f61df857cc041f0f5bd8c.tar.gz org.eclipse.cdt-5099040937cf056d2b4f61df857cc041f0f5bd8c.tar.xz org.eclipse.cdt-5099040937cf056d2b4f61df857cc041f0f5bd8c.zip |
add support for IIndexFragment properties
7 files changed, 417 insertions, 6 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBPropertiesTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBPropertiesTests.java new file mode 100644 index 00000000000..e63210c51a2 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBPropertiesTests.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2007 Symbian Software Systems and others. + * 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: + * Andrew Ferguson (Symbian) - Initial implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.pdom.tests; + +import java.io.File; +import java.util.Iterator; +import java.util.Properties; + +import junit.framework.Test; + +import org.eclipse.cdt.core.testplugin.util.BaseTestCase; +import org.eclipse.cdt.internal.core.pdom.db.DBProperties; +import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.core.runtime.CoreException; + +/** + * Sanity check the DBProperties class + */ +public class DBPropertiesTests extends BaseTestCase { + File dbLoc; + Database db; + + public static Test suite() { + return suite(DBPropertiesTests.class); + } + + protected void setUp() throws Exception { + dbLoc = File.createTempFile("test", "db"); + dbLoc.deleteOnExit(); + db = new Database(dbLoc); + } + + protected void tearDown() throws Exception { + db.close(); + } + + public void testBasic() throws CoreException { + DBProperties properties = new DBProperties(db); + Properties expected = System.getProperties(); + for(Iterator i = expected.keySet().iterator(); i.hasNext(); ) { + String key = (String) i.next(); + String value = expected.getProperty(key); + if(value!=null) { + properties.setProperty(key, value); + } + } + for(Iterator i = expected.keySet().iterator(); i.hasNext(); ) { + String key = (String) i.next(); + String aValue = properties.getProperty(key); + assertEquals(expected.getProperty(key), aValue); + } + for(Iterator i = expected.keySet().iterator(); i.hasNext(); ) { + String key = (String) i.next(); + properties.removeProperty(key); + } + assertEquals(0, properties.getKeySet().size()); + + properties.delete(); + } + + + public void testLong() throws Exception { + DBProperties ps = new DBProperties(db); + + StringBuffer largeValue = new StringBuffer(); + for(int i=0; i<Database.CHUNK_SIZE*2; i+=64) { + largeValue.append("********"); + ps.setProperty("key", largeValue.toString()); + ps.setProperty(largeValue.toString(), "value"); + } + + assertEquals(largeValue.toString(), ps.getProperty("key")); + assertEquals("value", ps.getProperty(largeValue.toString())); + + ps.delete(); + } + + public void testNulls() throws Exception { + DBProperties ps= new DBProperties(db); + try { + ps.setProperty(null, "val1"); + fail("NullPointerException expected"); + } catch(NullPointerException e) {} + + try { + ps.setProperty("key", null); + fail("NullPointerException expected"); + } catch(NullPointerException e) {} + + try { + ps.setProperty(null, null); + fail("NullPointerException expected"); + } catch(NullPointerException e) {} + + assertFalse(ps.removeProperty(null)); + + assertNull(ps.getProperty(null)); + + String s= ""+System.currentTimeMillis(); + assertEquals(s, ps.getProperty(null,s)); + } + + public void testSeq() throws Exception { + DBProperties ps = new DBProperties(db); + + ps.setProperty("a", "b"); + assertEquals("b", ps.getProperty("a")); + assertEquals(1, ps.getKeySet().size()); + + ps.setProperty("b", "c"); + assertEquals("c", ps.getProperty("b")); + assertEquals(2, ps.getKeySet().size()); + + ps.setProperty("a", "c"); + assertEquals("c", ps.getProperty("a")); + assertEquals(2, ps.getKeySet().size()); + + boolean deleted = ps.removeProperty("c"); + assertEquals(false, deleted); + assertEquals(2, ps.getKeySet().size()); + + deleted = ps.removeProperty("a"); + assertEquals(true, deleted); + assertEquals(1, ps.getKeySet().size()); + + ps.delete(); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTests.java index 5182c0d8ed3..21422e049d9 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006 QNX Software Systems and others. + * Copyright (c) 2006, 2007 QNX Software Systems and others. * 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 @@ -8,6 +8,7 @@ * Contributors: * QNX - Initial API and implementation * IBM Corporation + * Andrew Ferguson (Symbian) *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; @@ -24,6 +25,7 @@ public class PDOMTests extends TestSuite { TestSuite suite = new PDOMTests(); suite.addTest(DBTest.suite()); + suite.addTest(DBPropertiesTests.suite()); suite.addTest(PDOMSearchTest.suite()); suite.addTestSuite(PDOMLocationTests.class); suite.addTestSuite(EnumerationTests.class); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java index e2608bc0658..853eadf9c58 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java @@ -157,4 +157,12 @@ public interface IIndexFragment { * @return */ IIndexLinkage[] getLinkages(); + + /** + * Read the named property in this fragment + * @param key a case-sensitive identifier for a property, or null + * @return the value associated with the key, or null if either no such property is set, or the specified key was null + * @throws CoreException + */ + public String getProperty(String propertyName) throws CoreException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java index 3550708aca8..33cc5795a06 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2007 Wind River Systems, Inc. and others. * 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 @@ -57,4 +57,14 @@ public interface IWritableIndexFragment extends IIndexFragment { * Releases a write lock, reestablishing a certain amount of read locks. */ void releaseWriteLock(int establishReadLockCount); + + /** + * Write the key, value mapping to the fragment properties. If a mapping for the + * same key already exists, it is overwritten. + * @param key a non-null property name + * @param value a value to associate with the key. may not be null. + * @throws CoreException + * @throws NullPointerException if key is null + */ + public void setProperty(String propertyName, String value) throws CoreException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 7968524e6db..2fbed745670 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -46,6 +46,7 @@ import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IIndexFragmentInclude; import org.eclipse.cdt.internal.core.index.IIndexFragmentName; import org.eclipse.cdt.internal.core.pdom.db.BTree; +import org.eclipse.cdt.internal.core.pdom.db.DBProperties; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.BindingCollector; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMLinkageFactory; @@ -67,10 +68,9 @@ import org.eclipse.core.runtime.Status; * @author Doug Schaefer */ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { + protected Database db; - private Database db; - - public static final int VERSION = 25; + public static final int VERSION = 26; // 0 - the beginning of it all // 1 - first change to kick off upgrades // 2 - added file inclusions @@ -97,9 +97,11 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { // 23 - types on c-variables, return types on c-functions // 24 - file local scopes (161216) // 25 - change ordering of bindings (175275) + // 26 - add properties storage public static final int LINKAGES = Database.DATA_AREA; public static final int FILE_INDEX = Database.DATA_AREA + 4; + public static final int PROPERTIES = Database.DATA_AREA + 8; // Local caches private BTree fileIndex; @@ -633,4 +635,8 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { } return (IIndexFragmentBinding[]) result.toArray(new IIndexFragmentBinding[result.size()]); } + + public String getProperty(String propertyName) throws CoreException { + return new DBProperties(db, PROPERTIES).getProperty(propertyName); + } }
\ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java index 0f6424159bd..90882d23f3d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2007 Wind River Systems, Inc. and others. * 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 @@ -23,6 +23,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexLocationConverter; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; +import org.eclipse.cdt.internal.core.pdom.db.DBProperties; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; @@ -69,4 +70,8 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { } return result; } + + public void setProperty(String propertyName, String value) throws CoreException { + new DBProperties(db, PROPERTIES).setProperty(propertyName, value); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/DBProperties.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/DBProperties.java new file mode 100644 index 00000000000..d392361a11c --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/DBProperties.java @@ -0,0 +1,244 @@ +/******************************************************************************* + * Copyright (c) 2007 Symbian Software Systems and others. + * 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: + * Andrew Ferguson (Symbian) - Initial implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.pdom.db; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; + +/** + * DBProperties is a bare-bones implementation of a String->String mapping. It is neither + * a Map or a Properties subclass, because of their more general applications. + */ +public class DBProperties { + static final int PROP_INDEX = 0; + static final int RECORD_SIZE = 4; + + protected BTree index; + protected Database db; + protected int record; + + /** + * Allocate storage for a new DBProperties record in the specified database + * @param db + * @throws CoreException + */ + public DBProperties(Database db) throws CoreException { + this.record= db.malloc(4); + this.index= new BTree(db, record + PROP_INDEX, DBProperty.getComparator(db)); + this.db= db; + } + + /** + * Creates an object for accessing an existing DBProperties record at the specified location of the specified database + * @param db + * @param record + * @throws CoreException + */ + public DBProperties(Database db, int record) throws CoreException { + this.record= record; + this.index= new BTree(db, record + PROP_INDEX, DBProperty.getComparator(db)); + this.db= db; + } + + /** + * Read the named property from this properties storage + * @param key a case-sensitive identifier for a property, or null + * @return the value associated with the key, or null if either no such property is set, or the specified key was null + * @throws CoreException + */ + public String getProperty(String key) throws CoreException { + if(key!=null) { + DBProperty existing= DBProperty.search(db, index, key); + if(existing!=null) { + return existing.getValue().getString(); + } + } + return null; + } + + /** + * Read the named property from this properties storage, returning the default value if there is no such property + * @param key a case-sensitive identifier for a property, or null + * @param defaultValue a value to return in case the specified key was null + * @return the value associated with the key, or the specified default value if either no such property is set, or + * the specified key was null + * @throws CoreException + */ + public String getProperty(String key, String defaultValue) throws CoreException { + String val= getProperty(key); + return (val == null) ? defaultValue : val; + } + + /** + * Returns a Set of property names (Strings) stored in this object + * @return a Set of property names (Strings) stored in this object + * @throws CoreException + */ + public Set getKeySet() throws CoreException { + return DBProperty.getKeySet(db, index); + } + + /** + * Write the key, value mapping to the properties. If a mapping for the + * same key already exists, it is overwritten. + * @param key a non-null property name + * @param value a value to associate with the key. may not be null. + * @throws CoreException + * @throws NullPointerException if key is null + */ + public void setProperty(String key, String value) throws CoreException { + removeProperty(key); + DBProperty newProperty= new DBProperty(db, key, value); + index.insert(newProperty.getRecord()); + } + + /** + * Deletes a property from this DBProperties object + * @param key + * @return whether a property with matching key existed and was removed, or false if the key was null + * @throws CoreException + */ + public boolean removeProperty(String key) throws CoreException { + if(key!=null) { + DBProperty existing= DBProperty.search(db, index, key); + if(existing != null) { + index.delete(existing.getRecord()); + existing.delete(); + return true; + } + } + return false; + } + + /** + * Deletes all properties, does not delete the record associated with the object itself - that is + * it can be repopulated. + * @throws CoreException + */ + private void clear() throws CoreException { + index.accept(new IBTreeVisitor(){ + public int compare(int record) throws CoreException { + return 0; + } + public boolean visit(int record) throws CoreException { + new DBProperty(db, record).delete(); + return false; // there should never be duplicates + } + }); + } + + /** + * Deletes all properties stored in this object and the record associated with this object itself. + * <br><br> + * <b>The behaviour of objects of this class after calling this method is undefined</b> + * @throws CoreException + */ + public void delete() throws CoreException { + clear(); + db.free(record); + } + + private static class DBProperty { + static final int KEY = 0; + static final int VALUE = 4; + static final int RECORD_SIZE = 8; + + Database db; + int record; + + public int getRecord() { + return record; + } + + /** + * Allocates and initializes a record in the specified database for a DBProperty record + * @param db + * @param key a non-null property name + * @param value a non-null property value + * @throws CoreException + */ + DBProperty(Database db, String key, String value) throws CoreException { + assert key!=null; + assert value!=null; + IString dbkey= db.newString(key); + IString dbvalue= db.newString(value); + this.record= db.malloc(RECORD_SIZE); + db.putInt(record + KEY, dbkey.getRecord()); + db.putInt(record + VALUE, dbvalue.getRecord()); + this.db= db; + } + + /** + * Returns an object for accessing an existing DBProperty record at the specified location in the + * specified database + * @param db + * @param record + */ + DBProperty(Database db, int record) { + this.record= record; + this.db= db; + } + + public IString getKey() throws CoreException { + return db.getString(db.getInt(record + KEY)); + } + + public IString getValue() throws CoreException { + return db.getString(db.getInt(record + VALUE)); + } + + public static IBTreeComparator getComparator(final Database db) { + return new IBTreeComparator() { + public int compare(int record1, int record2) throws CoreException { + IString left= db.getString(db.getInt(record1 + KEY)); + IString right= db.getString(db.getInt(record2 + KEY)); + return left.compare(right, true); + } + }; + } + + public static DBProperty search(final Database db, final BTree index, final String key) throws CoreException { + final DBProperty[] result= new DBProperty[1]; + index.accept(new IBTreeVisitor(){ + public int compare(int record) throws CoreException { + return db.getString(db.getInt(record + KEY)).compare(key, true); + } + public boolean visit(int record) throws CoreException { + result[0] = new DBProperty(db, record); + return false; // there should never be duplicates + } + }); + return result[0]; + } + + public static Set getKeySet(final Database db, final BTree index) throws CoreException { + final Set result= new HashSet(); + index.accept(new IBTreeVisitor(){ + public int compare(int record) throws CoreException { + return 0; + } + public boolean visit(int record) throws CoreException { + result.add(new DBProperty(db, record).getKey().getString()); + return true; // there should never be duplicates + } + }); + return result; + } + + public void delete() throws CoreException { + db.getString(db.getInt(record + KEY)).delete(); + db.getString(db.getInt(record + VALUE)).delete(); + db.free(record); + } + } +} |