You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ju...@apache.org on 2010/06/22 20:39:51 UTC

svn commit: r956972 - in /sling/trunk: bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ launchpad/integration-tests/ launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/

Author: justin
Date: Tue Jun 22 18:39:51 2010
New Revision: 956972

URL: http://svn.apache.org/viewvc?rev=956972&view=rev
Log:
SLING-1569 - fixing the handling of the WeakReference hint. Uses reflection to avoid dependency upon JCR 2. If reflection fails to find the method (i.e. this is running on JCR 1), a Reference property is created instead.

Modified:
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java
    sling/trunk/launchpad/integration-tests/pom.xml
    sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/ReferenceTypeHintTest.java

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java?rev=956972&r1=956971&r2=956972&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java Tue Jun 22 18:39:51 2010
@@ -16,12 +16,18 @@
  */
 package org.apache.sling.servlets.post.impl.helper;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
  * Takes a string representation of a node (either a path or a uuid) and tries for parse it.
  */
@@ -29,56 +35,86 @@ public class ReferenceParser {
 
     private final Session session;
 
+    private static final Logger logger = LoggerFactory.getLogger(ReferenceParser.class);
+
     public ReferenceParser(Session session) {
         this.session = session;
     }
 
     /**
-     * Parses the given source string and returns the corresponding node.
+     * Parses the given source string and returns the correct Value object.
      * If no node matches returns <code>null</code>.
      * <p/>
      *
      * @param value a path or UUID
-     * @return the node or <code>null</code>
+     * @param factory the value factory
+     * @param weak true to create a WeakReference value
+     * @return the value or <code>null</code>
      * @throws RepositoryException
      */
-    public Node parse(String value) throws RepositoryException {
-        try {
-            if (session.itemExists(value)) {
-                return (Node) session.getItem(value);
-            }
-        } catch (RepositoryException ignore) {
-            // we ignore this
+    public Value parse(String value, ValueFactory factory, boolean weak) throws RepositoryException {
+        Node n = parse(value);
+        if (n == null) {
+            return null;
         }
-        try {
-            return session.getNodeByUUID(value);
-        } catch (RepositoryException ignore) {
-            // we ignore this
-        }
-        return null;
+        return createReferenceValue(n, factory, weak);
     }
 
     /**
-     * Parses the given source strings and returns the respective jcr Node value
+     * Parses the given source strings and returns the respective reference value
      * instances. If no node matches for any of the sources
      * returns <code>null</code>.
      * <p/>
      *
      * @param values path or UUID strings
      * @param factory the value factory
-     * @return the nodes or <code>null</code>
+     * @param weak true to create a WeakReference value
+     * @return the values or <code>null</code>
      * @throws RepositoryException
      */
-    public Value[] parse(String[] values, ValueFactory factory) throws RepositoryException {
+    public Value[] parse(String[] values, ValueFactory factory, boolean weak) throws RepositoryException {
         Value ret[] = new Value[values.length];
         for (int i=0; i< values.length; i++) {
             Node n = parse(values[i]);
             if (n == null) {
                 return null;
             }
-            ret[i] = factory.createValue(n);
+            ret[i] = createReferenceValue(n, factory, weak);
         }
         return ret;
     }
 
+    private Value createReferenceValue(Node node, ValueFactory factory, boolean weak) throws RepositoryException {
+        if (weak) {
+            try {
+                final Method m = factory.getClass().getMethod("createValue", new Class[] { Node.class, Boolean.TYPE });
+                return (Value) m.invoke(factory, node, true);
+            } catch (NoSuchMethodException e) {
+                logger.warn("A WeakReference type hint was received, but JCR 2 isn't available. Falling back to Reference type.");
+                return factory.createValue(node);
+            } catch (Exception e) {
+                logger.error("Unable to create WeakReference Value.", e);
+                return null;
+            }
+        } else {
+            return factory.createValue(node);
+        }
+    }
+
+    private Node parse(String value) throws RepositoryException {
+        try {
+            if (session.itemExists(value)) {
+                return (Node) session.getItem(value);
+            }
+        } catch (RepositoryException ignore) {
+            // we ignore this
+        }
+        try {
+            return session.getNodeByUUID(value);
+        } catch (RepositoryException ignore) {
+            // we ignore this
+        }
+        return null;
+    }
+
 }

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java?rev=956972&r1=956971&r2=956972&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java Tue Jun 22 18:39:51 2010
@@ -191,6 +191,7 @@ public class SlingPropertyValueHandler {
      */
     private void setPropertyAsIs(Node parent, RequestProperty prop)
             throws RepositoryException {
+        final ValueFactory valFac = parent.getSession().getValueFactory();
 
         // no explicit typehint
         int type = PropertyType.UNDEFINED;
@@ -248,17 +249,16 @@ public class SlingPropertyValueHandler {
                         return;
                     }
                 } else if (isReferencePropertyType(type)) {
-                    Node n = referenceParser.parse(values[0]);
-                    if (n != null) {
+                    Value v = referenceParser.parse(values[0], valFac, isWeakReference(type));
+                    if (v != null) {
                         if ( prop.hasMultiValueTypeHint() ) {
-                            final Value[] array = new Value[1];
-                            array[0] = parent.getSession().getValueFactory().createValue(n);
+                            final Value[] array = new Value[] { v };
                             changes.add(Modification.onModified(
                                 parent.setProperty(prop.getName(), array).getPath()
                             ));
                         } else {
                             changes.add(Modification.onModified(
-                                    parent.setProperty(prop.getName(), n).getPath()
+                                    parent.setProperty(prop.getName(), v).getPath()
                                 ));
                         }
                         return;
@@ -287,7 +287,6 @@ public class SlingPropertyValueHandler {
 
             if (type == PropertyType.DATE) {
                 // try conversion
-                ValueFactory valFac = parent.getSession().getValueFactory();
                 Value[] c = dateParser.parse(values, valFac);
                 if (c != null) {
                     changes.add(Modification.onModified(
@@ -297,8 +296,7 @@ public class SlingPropertyValueHandler {
                 }
             } else if (isReferencePropertyType(type)) {
                 // try conversion
-                ValueFactory valFac = parent.getSession().getValueFactory();
-                Value[] n = referenceParser.parse(values, valFac);
+                Value[] n = referenceParser.parse(values, valFac, isWeakReference(type));
                 if (n != null) {
                     changes.add(Modification.onModified(
                         parent.setProperty(prop.getName(), n).getPath()
@@ -321,6 +319,10 @@ public class SlingPropertyValueHandler {
         return propertyType == PropertyType.REFERENCE || propertyType == PROPERTY_TYPE_WEAKREFERENCE;
     }
 
+    private boolean isWeakReference(int propertyType) {
+        return propertyType == PROPERTY_TYPE_WEAKREFERENCE;
+    }
+
     /**
      * Defines an auto property behavior
      */

Modified: sling/trunk/launchpad/integration-tests/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/pom.xml?rev=956972&r1=956971&r2=956972&view=diff
==============================================================================
--- sling/trunk/launchpad/integration-tests/pom.xml (original)
+++ sling/trunk/launchpad/integration-tests/pom.xml Tue Jun 22 18:39:51 2010
@@ -152,5 +152,11 @@
       <artifactId>slf4j-simple</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+    	<groupId>xmlunit</groupId>
+    	<artifactId>xmlunit</artifactId>
+    	<version>1.3</version>
+    	<scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
\ No newline at end of file

Modified: sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/ReferenceTypeHintTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/ReferenceTypeHintTest.java?rev=956972&r1=956971&r2=956972&view=diff
==============================================================================
--- sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/ReferenceTypeHintTest.java (original)
+++ sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/ReferenceTypeHintTest.java Tue Jun 22 18:39:51 2010
@@ -16,6 +16,7 @@
  */
 package org.apache.sling.launchpad.webapp.integrationtest.servlets.post;
 
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -24,6 +25,13 @@ import org.apache.sling.commons.json.JSO
 import org.apache.sling.commons.testing.integration.HttpTestBase;
 import org.apache.sling.commons.testing.integration.NameValuePairList;
 import org.apache.sling.servlets.post.SlingPostConstants;
+import org.custommonkey.xmlunit.NamespaceContext;
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLAssert;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.custommonkey.xmlunit.exceptions.XpathException;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
 
 /**
  * Integration test of reference type hints in the post servlet.
@@ -31,27 +39,59 @@ import org.apache.sling.servlets.post.Sl
 public class ReferenceTypeHintTest extends HttpTestBase {
     public static final String TEST_BASE_PATH = "/sling-tests";
     private String postUrl;
+    private String firstCreatedNodeUrl;
+    private String firstUuid;
+    private String firstPath;
+    private String secondCreatedNodeUrl;
+    private String secondUuid;
+    private String secondPath;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
-    }
 
-    public void testReferenceTypes() throws Exception {
+
+        Map<String,String> m = new HashMap<String,String>();
+        m.put("sv", "http://www.jcp.org/jcr/sv/1.0");
+
+        NamespaceContext ctx = new SimpleNamespaceContext(m);
+        XMLUnit.setXpathNamespaceContext(ctx);
+
+
         final NameValuePairList props = new NameValuePairList();
         props.add("a", "");
         props.add("jcr:mixinTypes", "mix:referenceable");
 
-        final String firstCreatedNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props, null, false);
-        final String firstUuid = getProperty(firstCreatedNodeUrl, "jcr:uuid");
-        final String firstPath = getPath(firstCreatedNodeUrl);
-
-        final String secondCreatedNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props, null, false);
-        final String secondUuid = getProperty(secondCreatedNodeUrl, "jcr:uuid");
-        final String secondPath = getPath(secondCreatedNodeUrl);
+        firstCreatedNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props, null, false);
+        firstUuid = getProperty(firstCreatedNodeUrl, "jcr:uuid");
+        firstPath = getPath(firstCreatedNodeUrl);
+
+        secondCreatedNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props, null, false);
+        secondUuid = getProperty(secondCreatedNodeUrl, "jcr:uuid");
+        secondPath = getPath(secondCreatedNodeUrl);
+    }
 
-        props.clear();
+    public void testReferenceTypesCreatedFromUuids() throws Exception {
+        final NameValuePairList props = new NameValuePairList();
+        props.add("r", firstUuid);
+        props.add("r@TypeHint", "Reference");
+        props.add("w", firstUuid);
+        props.add("w@TypeHint", "WeakReference");
+        props.add("rs", firstUuid);
+        props.add("rs", secondUuid);
+        props.add("rs@TypeHint", "Reference[]");
+        props.add("ws", firstUuid);
+        props.add("ws", secondUuid);
+        props.add("ws@TypeHint", "WeakReference[]");
+        final String referencingNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX,
+                props, null, false);
+
+        verifyReferences(referencingNodeUrl);
+    }
+
+    public void testReferenceTypesCreatedFromPath() throws Exception {
+        final NameValuePairList props = new NameValuePairList();
         props.add("r", firstPath);
         props.add("r@TypeHint", "Reference");
         props.add("w", firstPath);
@@ -65,11 +105,15 @@ public class ReferenceTypeHintTest exten
         final String referencingNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX,
                 props, null, false);
 
-        String refCreatedValue = getProperty(referencingNodeUrl, "r");
-        String weakrefCreatedValue = getProperty(referencingNodeUrl, "w");
+        verifyReferences(referencingNodeUrl);
+    }
 
-        String[] refCreatedValues = getPropertyArray(referencingNodeUrl, "rs");
-        String[] weakrefCreatedValues = getPropertyArray(referencingNodeUrl, "ws");
+    private void verifyReferences(final String referencingNodeUrl) throws Exception {
+        final String refCreatedValue = getProperty(referencingNodeUrl, "r");
+        final String weakrefCreatedValue = getProperty(referencingNodeUrl, "w");
+
+        final String[] refCreatedValues = getPropertyArray(referencingNodeUrl, "rs");
+        final String[] weakrefCreatedValues = getPropertyArray(referencingNodeUrl, "ws");
 
         assertEquals(firstUuid, refCreatedValue);
         assertEquals(firstUuid, weakrefCreatedValue);
@@ -77,6 +121,17 @@ public class ReferenceTypeHintTest exten
         assertEquals(firstUuid, weakrefCreatedValues[0]);
         assertEquals(secondUuid, refCreatedValues[1]);
         assertEquals(secondUuid, weakrefCreatedValues[1]);
+
+        final String sysView = getSystemView(referencingNodeUrl);
+
+        XMLAssert.assertXpathEvaluatesTo("Reference", "//sv:property[@sv:name='r']/@sv:type", sysView);
+        XMLAssert.assertXpathEvaluatesTo("WeakReference", "//sv:property[@sv:name='w']/@sv:type", sysView);
+        XMLAssert.assertXpathEvaluatesTo("Reference", "//sv:property[@sv:name='rs']/@sv:type", sysView);
+        XMLAssert.assertXpathEvaluatesTo("WeakReference", "//sv:property[@sv:name='ws']/@sv:type", sysView);
+    }
+
+    private String getSystemView(String url) throws IOException, SAXException {
+        return getContent(url + ".sysview.xml", CONTENT_TYPE_XML);
     }
 
     private String getPath(String url) {