You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2009/06/22 12:07:05 UTC

svn commit: r787183 - in /jackrabbit/trunk: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ jackrabbit-core...

Author: mreutegg
Date: Mon Jun 22 10:07:05 2009
New Revision: 787183

URL: http://svn.apache.org/viewvc?rev=787183&view=rev
Log:
JCR-2166: Provide query support for WEAKREFERENCE reverse lookup

Added:
    jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/GetWeakReferencesTest.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SearchManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryManagerImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FieldNames.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeIndexer.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SlowQueryHandler.java
    jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/TestAll.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=787183&r1=787182&r2=787183&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Mon Jun 22 10:07:05 2009
@@ -26,6 +26,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.Collection;
+import java.util.Collections;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Binary;
@@ -95,6 +97,7 @@
 import org.apache.jackrabbit.core.version.LabelVersionSelector;
 import org.apache.jackrabbit.core.version.VersionImpl;
 import org.apache.jackrabbit.core.version.VersionSelector;
+import org.apache.jackrabbit.core.query.QueryManagerImpl;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
@@ -103,6 +106,7 @@
 import org.apache.jackrabbit.spi.commons.name.PathBuilder;
 import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.util.ChildrenCollectorFilter;
+import org.apache.jackrabbit.util.ISO9075;
 import org.apache.jackrabbit.uuid.UUID;
 import org.apache.jackrabbit.value.ValueHelper;
 import org.slf4j.Logger;
@@ -4660,53 +4664,53 @@
      * {@inheritDoc}
      */
     public PropertyIterator getWeakReferences() throws RepositoryException {
-        return getWeakReferences(null);
+        // check state of this instance
+        sanityCheck();
+
+        Value ref = getSession().getValueFactory().createValue(this, true);
+        List<Property> props = new ArrayList<Property>();
+        QueryManagerImpl qm = (QueryManagerImpl) session.getWorkspace().getQueryManager();
+        for (Node n : qm.getWeaklyReferringNodes(this)) {
+            for (PropertyIterator it = n.getProperties(); it.hasNext(); ) {
+                Property p = it.nextProperty();
+                if (p.getType() == PropertyType.WEAKREFERENCE) {
+                    Collection<Value> refs;
+                    if (p.isMultiple()) {
+                        refs = Arrays.asList(p.getValues());
+                    } else {
+                        refs = Collections.singleton(p.getValue());
+                    }
+                    if (refs.contains(ref)) {
+                        props.add(p);
+                    }
+                }
+            }
+        }
+        return new PropertyIteratorAdapter(props);
     }
 
     /**
      * {@inheritDoc}
      */
     public PropertyIterator getWeakReferences(String name) throws RepositoryException {
+        if (name == null) {
+            return getWeakReferences();
+        }
+
         // check state of this instance
         sanityCheck();
 
-        // TODO tweak query implemention in order to support WEAKREFERENCE reverse lookup
         try {
+            StringBuilder stmt = new StringBuilder();
+            stmt.append("//*[@").append(ISO9075.encode(name));
+            stmt.append(" = '").append(data.getId()).append("']");
             Query q = session.getWorkspace().getQueryManager().createQuery(
-                    "//*[jcr:contains(., '" + data.getId() + "')]",
-                    //"//*[@*='" + data.getId() + "']",
-                    Query.XPATH);
+                    stmt.toString(), Query.XPATH);
             QueryResult result = q.execute();
             ArrayList<Property> l = new ArrayList<Property>();
             for (NodeIterator nit = result.getNodes(); nit.hasNext();) {
                 Node n = nit.nextNode();
-                for (PropertyIterator pit = n.getProperties(); pit.hasNext();) {
-                    Property p = pit.nextProperty();
-                    if (name != null && !name.equals(p.getName())) {
-                        continue;
-                    }
-                    if (p.getType() == PropertyType.WEAKREFERENCE) {
-                        boolean containsId = false;
-                        if (p.isMultiple()) {
-                            // multi-valued
-                            Value[] v = p.getValues();
-                            for (int i = 0; i < v.length; i++) {
-                                if (getIdentifier().equals(v[i].getString())) {
-                                    containsId = true;
-                                    break;
-                                }
-                            }
-                        } else {
-                            // single-valued
-                            if (getIdentifier().equals(p.getString())) {
-                                containsId = true;
-                            }
-                        }
-                        if (containsId) {
-                            l.add(p);
-                        }
-                    }
-                }
+                l.add(n.getProperty(name));
             }
             if (l.isEmpty()) {
                 return PropertyIteratorAdapter.EMPTY;

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SearchManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SearchManager.java?rev=787183&r1=787182&r2=787183&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SearchManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SearchManager.java Mon Jun 22 10:07:05 2009
@@ -316,6 +316,21 @@
     }
 
     /**
+     * Returns the ids of the nodes that refer to the node with <code>id</code>
+     * by weak references.
+     *
+     * @param id the id of the target node.
+     * @return the ids of the referring nodes.
+     * @throws RepositoryException if an error occurs.
+     * @throws IOException         if an error occurs while reading from the
+     *                             index.
+     */
+    public Iterable<NodeId> getWeaklyReferringNodes(NodeId id)
+            throws RepositoryException, IOException {
+        return handler.getWeaklyReferringNodes(id);
+    }
+
+    /**
      * Checks if the given event should be excluded based on the
      * {@link #excludePath} setting.
      *

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java?rev=787183&r1=787182&r2=787183&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java Mon Jun 22 10:07:05 2009
@@ -131,5 +131,17 @@
      * @return the name of the query class to use.
      */
     String getQueryClass();
-    
+
+    /**
+     * Returns the ids of the nodes that refer to the node with <code>id</code>
+     * by weak references.
+     *
+     * @param id the id of the target node.
+     * @return the ids of the referring nodes.
+     * @throws RepositoryException if an error occurs.
+     * @throws IOException         if an error occurs while reading from the
+     *                             index.
+     */
+    public Iterable<NodeId> getWeaklyReferringNodes(NodeId id)
+            throws RepositoryException, IOException;
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryManagerImpl.java?rev=787183&r1=787182&r2=787183&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryManagerImpl.java Mon Jun 22 10:07:05 2009
@@ -18,6 +18,8 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.ArrayList;
+import java.io.IOException;
 
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
@@ -30,9 +32,11 @@
 import org.apache.jackrabbit.core.ItemManager;
 import org.apache.jackrabbit.core.SearchManager;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelFactoryImpl;
 import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.uuid.UUID;
 
 /**
  * This class implements the {@link QueryManager} interface.
@@ -133,6 +137,31 @@
         return qomFactory;
     }
 
+    //-------------------------< Jackrabbit internal >--------------------------
+
+    /**
+     * Returns the ids of the nodes that refer to the <code>node</code> by weak
+     * references.
+     *
+     * @param node the target node.
+     * @return the referring nodes.
+     * @throws RepositoryException if an error occurs.
+     */
+    public Iterable<Node> getWeaklyReferringNodes(Node node)
+            throws RepositoryException {
+        sanityCheck();
+        List<Node> nodes = new ArrayList<Node>();
+        try {
+            NodeId nodeId = new NodeId(UUID.fromString(node.getIdentifier()));
+            for (NodeId id : searchMgr.getWeaklyReferringNodes(nodeId)) {
+                nodes.add(session.getNodeById(id));
+            }
+        } catch (IOException e) {
+            throw new RepositoryException(e);
+        }
+        return nodes;
+    }
+
     //------------------------< testing only >----------------------------------
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FieldNames.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FieldNames.java?rev=787183&r1=787182&r2=787183&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FieldNames.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FieldNames.java Mon Jun 22 10:07:05 2009
@@ -112,6 +112,11 @@
     public static final String SHAREABLE_NODE = "_:SHAREABLE_NODE".intern();
 
     /**
+     * Name of the field that contains all weak reference property values.
+     */
+    public static final String WEAK_REFS = "_:WEAK_REFS".intern();
+
+    /**
      * Returns a named length for use as a term in the index. The named length
      * is of the form: <code>propertyName</code> + '[' +
      * {@link LongField#longToString(long)}.

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeIndexer.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeIndexer.java?rev=787183&r1=787182&r2=787183&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeIndexer.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeIndexer.java Mon Jun 22 10:07:05 2009
@@ -44,7 +44,6 @@
 import java.io.InputStream;
 import java.io.Reader;
 import java.util.Calendar;
-import java.util.Iterator;
 import java.util.Set;
 import java.util.List;
 import java.util.ArrayList;
@@ -113,7 +112,7 @@
      * List of {@link FieldNames#FULLTEXT} fields which should not be used in
      * an excerpt.
      */
-    protected List doNotUseInExcerpt = new ArrayList();
+    protected List<Fieldable> doNotUseInExcerpt = new ArrayList<Fieldable>();
 
     /**
      * Creates a new node indexer.
@@ -199,8 +198,8 @@
                 addParentChildRelation(doc, node.getParentId());
             } else {
                 // shareable node
-                for (Iterator it = node.getSharedSet().iterator(); it.hasNext(); ) {
-                    addParentChildRelation(doc, (NodeId) it.next());
+                for (NodeId id : node.getSharedSet()) {
+                    addParentChildRelation(doc, id);
                 }
                 // mark shareable nodes
                 doc.add(new Field(FieldNames.SHAREABLE_NODE, "",
@@ -215,23 +214,21 @@
             // unknown uri<->prefix mappings
         }
 
-        Set props = node.getPropertyNames();
-        for (Iterator it = props.iterator(); it.hasNext();) {
-            Name propName = (Name) it.next();
+        Set<Name> props = node.getPropertyNames();
+        for (Name propName : props) {
             PropertyId id = new PropertyId(node.getNodeId(), propName);
             try {
                 PropertyState propState = (PropertyState) stateProvider.getItemState(id);
 
                 // add each property to the _PROPERTIES_SET for searching
                 // beginning with V2
-                if (indexFormatVersion.getVersion()
-                        >= IndexFormatVersion.V2.getVersion()) {
+                if (indexFormatVersion.getVersion() >= IndexFormatVersion.V2.getVersion()) {
                     addPropertyName(doc, propState.getName());
                 }
 
                 InternalValue[] values = propState.getValues();
-                for (int i = 0; i < values.length; i++) {
-                    addValue(doc, values[i], propState.getName());
+                for (InternalValue value : values) {
+                    addValue(doc, value, propState.getName());
                 }
                 if (values.length > 1) {
                     // real multi-valued
@@ -245,8 +242,8 @@
         }
 
         // now add fields that are not used in excerpt (must go at the end)
-        for (Iterator it = doNotUseInExcerpt.iterator(); it.hasNext(); ) {
-            doc.add((Fieldable) it.next());
+        for (Fieldable field : doNotUseInExcerpt) {
+            doc.add(field);
         }
         return doc;
     }
@@ -302,7 +299,7 @@
                 break;
             case PropertyType.BOOLEAN:
                 if (isIndexed(name)) {
-                    addBooleanValue(doc, fieldName, Boolean.valueOf(value.getBoolean()));
+                    addBooleanValue(doc, fieldName, value.getBoolean());
                 }
                 break;
             case PropertyType.DATE:
@@ -312,12 +309,12 @@
                 break;
             case PropertyType.DOUBLE:
                 if (isIndexed(name)) {
-                    addDoubleValue(doc, fieldName, new Double(value.getDouble()));
+                    addDoubleValue(doc, fieldName, value.getDouble());
                 }
                 break;
             case PropertyType.LONG:
                 if (isIndexed(name)) {
-                    addLongValue(doc, fieldName, new Long(value.getLong()));
+                    addLongValue(doc, fieldName, value.getLong());
                 }
                 break;
             case PropertyType.REFERENCE:
@@ -538,7 +535,7 @@
      * @param internalValue The value for the field to add to the document.
      */
     protected void addDoubleValue(Document doc, String fieldName, Object internalValue) {
-        double doubleVal = ((Double) internalValue).doubleValue();
+        double doubleVal = (Double) internalValue;
         doc.add(createFieldWithoutNorms(fieldName, DoubleField.doubleToString(doubleVal),
                 PropertyType.DOUBLE));
     }
@@ -553,7 +550,7 @@
      * @param internalValue The value for the field to add to the document.
      */
     protected void addLongValue(Document doc, String fieldName, Object internalValue) {
-        long longVal = ((Long) internalValue).longValue();
+        long longVal = (Long) internalValue;
         doc.add(createFieldWithoutNorms(fieldName, LongField.longToString(longVal),
                 PropertyType.LONG));
     }
@@ -576,7 +573,9 @@
     /**
      * Adds the reference value to the document as the named field. The value's
      * string representation is added as the reference data. Additionally the
-     * reference data is stored in the index.
+     * reference data is stored in the index. As of Jackrabbit 2.0 this method
+     * also adds the reference UUID as a {@link FieldNames#WEAK_REFS} field
+     * to the index if it is a weak reference.
      *
      * @param doc           The document to which to add the field
      * @param fieldName     The name of the field to add
@@ -591,6 +590,10 @@
         doc.add(new Field(FieldNames.PROPERTIES,
                 FieldNames.createNamedValue(fieldName, uuid),
                 Field.Store.YES, Field.Index.NO, Field.TermVector.NO));
+        if (weak) {
+            doc.add(new Field(FieldNames.WEAK_REFS, uuid, Field.Store.NO,
+                    Field.Index.NOT_ANALYZED_NO_NORMS));
+        }
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=787183&r1=787182&r2=787183&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java Mon Jun 22 10:07:05 2009
@@ -60,6 +60,9 @@
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.Similarity;
 import org.apache.lucene.search.SortComparatorSource;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.HitCollector;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.Fieldable;
@@ -694,6 +697,38 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    public Iterable<NodeId> getWeaklyReferringNodes(NodeId id)
+            throws RepositoryException, IOException {
+        final List<Integer> docs = new ArrayList<Integer>();
+        final List<NodeId> ids = new ArrayList<NodeId>();
+        final IndexReader reader = getIndexReader();
+        try {
+            IndexSearcher searcher = new IndexSearcher(reader);
+            try {
+                Query q = new TermQuery(new Term(
+                        FieldNames.WEAK_REFS, id.getUUID().toString()));
+                searcher.search(q, new HitCollector() {
+                    public void collect(int doc, float score) {
+                        docs.add(doc);
+                    }
+                });
+            } finally {
+                searcher.close();
+            }
+            for (Integer doc : docs) {
+                Document d = reader.document(doc, FieldSelectors.UUID);
+                UUID uuid = UUID.fromString(d.get(FieldNames.UUID));
+                ids.add(new NodeId(uuid));
+            }
+        } finally {
+            Util.closeOrRelease(reader);
+        }
+        return ids;
+    }
+
+    /**
      * This method returns the QueryNodeFactory used to parse Queries. This method
      * may be overridden to provide a customized QueryNodeFactory
      */

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SlowQueryHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SlowQueryHandler.java?rev=787183&r1=787182&r2=787183&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SlowQueryHandler.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SlowQueryHandler.java Mon Jun 22 10:07:05 2009
@@ -70,4 +70,9 @@
             throws InvalidQueryException {
         return null;
     }
+
+    public Iterable<NodeId> getWeaklyReferringNodes(NodeId id)
+            throws RepositoryException {
+        return null;
+    }
 }

Added: jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/GetWeakReferencesTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/GetWeakReferencesTest.java?rev=787183&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/GetWeakReferencesTest.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/GetWeakReferencesTest.java Mon Jun 22 10:07:05 2009
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.test.api;
+
+import javax.jcr.Node;
+import javax.jcr.Value;
+import javax.jcr.RepositoryException;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Property;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+
+/**
+ * <code>GetWeakReferencesTest</code> checks implementation of
+ * {@link Node#getWeakReferences()} and {@link Node#getWeakReferences(String)}.
+ */
+public class GetWeakReferencesTest extends AbstractJCRTest {
+
+    private Node target;
+
+    private Node referring;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        target = testRootNode.addNode(nodeName1, testNodeType);
+        if (!target.isNodeType(mixReferenceable)) {
+            if (!target.canAddMixin(mixReferenceable)) {
+                throw new NotExecutableException("cannot add mix:referenceable to node");
+            }
+            target.addMixin(mixReferenceable);
+        }
+        referring = testRootNode.addNode(nodeName2, testNodeType);
+        superuser.save();
+    }
+
+    public void testSingleValue() throws RepositoryException {
+        Value weakRef = vf.createValue(target, true);
+        referring.setProperty(propertyName1, weakRef);
+        superuser.save();
+
+        PropertyIterator it = target.getWeakReferences();
+        assertTrue("no weak references returned", it.hasNext());
+        Property p = it.nextProperty();
+        assertEquals("wrong weak reference property", referring.getProperty(propertyName1).getPath(), p.getPath());
+        assertFalse("no more weak references expected", it.hasNext());
+    }
+
+    public void testSingleValueWithName() throws RepositoryException {
+        Value weakRef = vf.createValue(target, true);
+        referring.setProperty(propertyName1, weakRef);
+        superuser.save();
+
+        PropertyIterator it = target.getWeakReferences(propertyName1);
+        assertTrue("no weak references returned", it.hasNext());
+        Property p = it.nextProperty();
+        assertEquals("wrong weak reference property", referring.getProperty(propertyName1).getPath(), p.getPath());
+        assertFalse("no more weak references expected", it.hasNext());
+    }
+
+    public void testMultiValues() throws RepositoryException {
+        Value weakRef = vf.createValue(target, true);
+        Value[] refs = new Value[]{weakRef, weakRef};
+        referring.setProperty(propertyName1, refs);
+        superuser.save();
+
+        PropertyIterator it = target.getWeakReferences();
+        assertTrue("no weak references returned", it.hasNext());
+        Property p = it.nextProperty();
+        assertEquals("wrong weak reference property", referring.getProperty(propertyName1).getPath(), p.getPath());
+        assertFalse("no more weak references expected", it.hasNext());
+    }
+
+    public void testMultiValuesWithName() throws RepositoryException {
+        Value weakRef = vf.createValue(target, true);
+        Value[] refs = new Value[]{weakRef, weakRef};
+        referring.setProperty(propertyName1, refs);
+        superuser.save();
+
+        PropertyIterator it = target.getWeakReferences(propertyName1);
+        assertTrue("no weak references returned", it.hasNext());
+        Property p = it.nextProperty();
+        assertEquals("wrong weak reference property", referring.getProperty(propertyName1).getPath(), p.getPath());
+        assertFalse("no more weak references expected", it.hasNext());
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/GetWeakReferencesTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/TestAll.java?rev=787183&r1=787182&r2=787183&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/TestAll.java Mon Jun 22 10:07:05 2009
@@ -141,7 +141,10 @@
         suite.addTestSuite(ValueFactoryTest.class);
 
         // JCR 2.0
-        
+
+        //// new node types
+        suite.addTestSuite(GetWeakReferencesTest.class);
+
         //// new Session features
         
         suite.addTestSuite(SessionRemoveItemTest.class);