jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From resc...@apache.org
Subject svn commit: r1200319 - in /jackrabbit/trunk: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/ jackrabbit-jcr2dav/ jackrabbit-spi2dav/ jackrabbit-spi2dav/src/mai...
Date Thu, 10 Nov 2011 13:11:53 GMT
Author: reschke
Date: Thu Nov 10 13:11:53 2011
New Revision: 1200319

URL: http://svn.apache.org/viewvc?rev=1200319&view=rev
Log:
JCR-2539: spi2dav: Observation's user data not property handled

User Data is transported in a Link header field using a JCR-specific extension link relation
and a "data" URI.

Added:
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java
    jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java
Modified:
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/JcrRemotingConstants.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java
    jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml
    jackrabbit/trunk/jackrabbit-spi2dav/pom.xml
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
    jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/JcrRemotingConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/JcrRemotingConstants.java?rev=1200319&r1=1200318&r2=1200319&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/JcrRemotingConstants.java
(original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/JcrRemotingConstants.java
Thu Nov 10 13:11:53 2011
@@ -150,4 +150,17 @@ public interface JcrRemotingConstants {
     public static final String REPORT_NODETYPES = "nodetypes";
     public static final String REPORT_REGISTERED_NAMESPACES = "registerednamespaces";
     public static final String REPORT_REPOSITORY_DESCRIPTORS = "repositorydescriptors";
+
+    /**
+     * RFC 5988 relation type for user data
+     * <p>
+     * We transport JCR User Data in a Link header field with this relation name
+     * <p>
+     * Example:
+     * 
+     * <pre>
+     * Link: <data:,my%20user%data>, rel="<i>RELATION_USER_DATA</i>"
+     * </pre>
+     */
+    public static final String RELATION_USER_DATA = NS_URI + "/user-data";
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java?rev=1200319&r1=1200318&r2=1200319&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java
Thu Nov 10 13:11:53 2011
@@ -16,6 +16,11 @@
  */
 package org.apache.jackrabbit.server;
 
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Enumeration;
+import java.util.Locale;
+
 import javax.jcr.Credentials;
 import javax.jcr.LoginException;
 import javax.jcr.Repository;
@@ -24,6 +29,10 @@ import javax.jcr.Session;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.util.LinkHeaderFieldParser;
+
 /**
  * This Class implements a default session provider uses a credentials provider.
  */
@@ -36,6 +45,7 @@ public class SessionProviderImpl impleme
 
     /**
      * Creates a new SessionProvider
+     * 
      * @param cp
      */
     public SessionProviderImpl(CredentialsProvider cp) {
@@ -45,15 +55,19 @@ public class SessionProviderImpl impleme
     /**
      * {@inheritDoc }
      */
-    public Session getSession(HttpServletRequest request, Repository repository,
-                              String workspace)
-        throws LoginException, RepositoryException, ServletException {
+    public Session getSession(HttpServletRequest request,
+            Repository repository, String workspace) throws LoginException,
+            RepositoryException, ServletException {
         Credentials creds = cp.getCredentials(request);
+        Session s;
         if (creds == null) {
-            return repository.login(workspace);
+            s = repository.login(workspace);
         } else {
-            return repository.login(creds, workspace);
+            s = repository.login(creds, workspace);
         }
+        String userData = getJcrUserData(request);
+        s.getWorkspace().getObservationManager().setUserData(userData);
+        return s;
     }
 
     /**
@@ -62,4 +76,44 @@ public class SessionProviderImpl impleme
     public void releaseSession(Session session) {
         session.logout();
     }
+
+    // find first link relation for JCR User Data
+    private String getJcrUserData(HttpServletRequest request) {
+        String jcrUserData = null;
+        Enumeration<?> fieldValues = request.getHeaders("link");
+        if (fieldValues.hasMoreElements()) {
+            LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser(fieldValues);
+            String target = lhfp
+                    .getFirstTargetForRelation(JcrRemotingConstants.RELATION_USER_DATA);
+            if (target != null) {
+                jcrUserData = getJcrUserData(target);
+            }
+        }
+        return jcrUserData;
+    }
+
+    // extracts User Data string from RFC 2397 "data" URI
+    // only supports the simple case of "data:,..." for now
+    private String getJcrUserData(String target) {
+        try {
+            URI datauri = new URI(target);
+
+            String scheme = datauri.getScheme();
+
+            // Poor Man's data: URI parsing
+            if (scheme != null
+                    && "data".equals(scheme.toLowerCase(Locale.ENGLISH))) {
+
+                String sspart = datauri.getRawSchemeSpecificPart();
+
+                if (sspart.startsWith(",")) {
+                    return Text.unescape(sspart.substring(1));
+                }
+            }
+        } catch (URISyntaxException ex) {
+            // not a URI, skip
+        }
+
+        return null;
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml?rev=1200319&r1=1200318&r2=1200319&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml (original)
+++ jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml Thu Nov 10 13:11:53 2011
@@ -76,8 +76,6 @@
                       org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddLockTokenToAnotherSession
                       org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockTransfer2
                       org.apache.jackrabbit.jcr2spi.lock.OpenScopedLockTest#testLogoutHasNoEffect

-                      <!-- JCR-2539 : user data (observation) -->
-                      org.apache.jackrabbit.test.api.observation.GetUserDataTest
                       <!-- JCR-2540 : move/reorder (observation) -->
                       org.apache.jackrabbit.test.api.observation.GetIdentifierTest#testNodeRemoved
                     
                       <!-- JCR-2541 : event journal -->

Modified: jackrabbit/trunk/jackrabbit-spi2dav/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/pom.xml?rev=1200319&r1=1200318&r2=1200319&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/pom.xml (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/pom.xml Thu Nov 10 13:11:53 2011
@@ -73,8 +73,6 @@
                   org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddInvalidLockToken
                   org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddLockTokenToAnotherSession
                   org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockTransfer2
-                  <!-- JCR-2539 : user data (observation) -->
-                  org.apache.jackrabbit.test.api.observation.GetUserDataTest
                   <!-- JCR-2540 : move/reorder (observation) -->
                   org.apache.jackrabbit.test.api.observation.GetIdentifierTest#testNodeRemoved
                   <!-- JCR-2541 : event journal -->

Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java?rev=1200319&r1=1200318&r2=1200319&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
Thu Nov 10 13:11:53 2011
@@ -375,6 +375,16 @@ public class RepositoryServiceImpl imple
                 method.setRequestHeader(ifH.getHeaderName(), ifH.getHeaderValue());
             }
         }
+
+        if (sessionInfo instanceof SessionInfoImpl) {
+            String userdata = ((SessionInfoImpl) sessionInfo).getUserData();
+            if (userdata != null) {
+                String escaped = Text.escape(userdata);
+                method.addRequestHeader("Link", "<data:," + escaped
+                        + ">; rel=\"" + JcrRemotingConstants.RELATION_USER_DATA
+                        + "\"");
+            }
+        }
     }
 
     private static void initMethod(DavMethod method, BatchImpl batchImpl, boolean addIfHeader)
throws RepositoryException {

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java?rev=1200319&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java
(added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java
Thu Nov 10 13:11:53 2011
@@ -0,0 +1,198 @@
+/*
+ * 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.webdav.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.util.ParameterParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Simple parser for HTTP Link header fields, as defined in RFC 5988.
+ */
+public class LinkHeaderFieldParser {
+
+    /**
+     * the default logger
+     */
+    private static Logger log = LoggerFactory
+            .getLogger(LinkHeaderFieldParser.class);
+
+    private final List<LinkRelation> relations;
+
+    public LinkHeaderFieldParser(List<String> fieldValues) {
+
+        List<LinkRelation> tmp = new ArrayList<LinkRelation>();
+
+        for (String s : fieldValues) {
+            addFields(tmp, s);
+        }
+
+        relations = Collections.unmodifiableList(tmp);
+    }
+
+    public LinkHeaderFieldParser(Enumeration<?> en) {
+
+        List<LinkRelation> tmp = new ArrayList<LinkRelation>();
+
+        while (en.hasMoreElements()) {
+            addFields(tmp, en.nextElement().toString());
+        }
+
+        relations = Collections.unmodifiableList(tmp);
+    }
+
+    public String getFirstTargetForRelation(String relationType) {
+
+        for (LinkRelation lr : relations) {
+
+            String relationNames = lr.getParameters().get("rel");
+            if (relationNames != null) {
+
+                // split rel value on whitespace
+                for (String rn : relationNames.toLowerCase(Locale.ENGLISH)
+                        .split("\\s")) {
+                    if (relationType.equals(rn)) {
+                        return lr.getTarget();
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+    // A single header field instance can contain multiple, comma-separated
+    // fields.
+    private void addFields(List<LinkRelation> l, String fieldValue) {
+
+        boolean insideAngleBrackets = false;
+        boolean insideDoubleQuotes = false;
+
+        for (int i = 0; i < fieldValue.length(); i++) {
+
+            char c = fieldValue.charAt(i);
+
+            if (insideAngleBrackets) {
+                insideAngleBrackets = c != '>';
+            } else if (insideDoubleQuotes) {
+                insideDoubleQuotes = c != '"';
+                if (c == '\\' && i < fieldValue.length() - 1) {
+                    // skip over next character
+                    c = fieldValue.charAt(++i);
+                }
+            } else {
+                insideAngleBrackets = c == '<';
+                insideDoubleQuotes = c == '"';
+
+                if (c == ',') {
+                    String v = fieldValue.substring(0, i);
+                    if (v.length() > 0) {
+                        try {
+                            l.add(new LinkRelation(v));
+                        } catch (Exception ex) {
+                            log.warn("parse error in Link Header field value",
+                                    ex);
+                        }
+                    }
+                    addFields(l, fieldValue.substring(i + 1));
+                    return;
+                }
+            }
+        }
+
+        if (fieldValue.length() > 0) {
+            try {
+                l.add(new LinkRelation(fieldValue));
+            } catch (Exception ex) {
+                log.warn("parse error in Link Header field value", ex);
+            }
+        }
+    }
+
+    private static class LinkRelation {
+
+        private static Pattern P = Pattern.compile("\\s*<(.*)>\\s*(.*)");
+
+        private String target;
+        private Map<String, String> parameters;
+
+        /**
+         * Parses a single link relation, consisting of <URI> and optional
+         * parameters.
+         * 
+         * @param field
+         *            field value
+         * @throws Exception
+         */
+        @SuppressWarnings("unchecked")
+        public LinkRelation(String field) throws Exception {
+
+            // find the link target using a regexp
+            Matcher m = P.matcher(field);
+            if (!m.matches()) {
+                throw new Exception("illegal Link header field value:" + field);
+            }
+
+            target = m.group(1);
+
+            // pass the remainder to the generic parameter parser
+            List<NameValuePair> params = (List<NameValuePair>) new ParameterParser()
+                    .parse(m.group(2), ';');
+
+            if (params.size() == 0) {
+                parameters = Collections.emptyMap();
+            } else if (params.size() == 1) {
+                NameValuePair nvp = params.get(0);
+                parameters = Collections.singletonMap(nvp.getName()
+                        .toLowerCase(Locale.ENGLISH), nvp.getValue());
+            } else {
+                parameters = new HashMap<String, String>();
+                for (NameValuePair p : params) {
+                    if (null != parameters.put(
+                            p.getName().toLowerCase(Locale.ENGLISH),
+                            p.getValue())) {
+                        throw new Exception("duplicate parameter + "
+                                + p.getName() + " field ignored");
+                    }
+                }
+            }
+        }
+
+        public String getTarget() {
+            return target;
+        }
+
+        public Map<String, String> getParameters() {
+            return parameters;
+        }
+
+        public String toString() {
+            return target + " " + parameters;
+        }
+    }
+}

Added: jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java?rev=1200319&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java
(added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java
Thu Nov 10 13:11:53 2011
@@ -0,0 +1,66 @@
+/*
+ * 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.webdav.util;
+
+import java.util.Collections;
+
+import org.apache.jackrabbit.webdav.util.LinkHeaderFieldParser;
+
+import junit.framework.TestCase;
+
+/**
+ * <code>LinkHeaderFieldParserTest</code>...
+ */
+public class LinkHeaderFieldParserTest extends TestCase {
+
+    public void testSimple() {
+        LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser(
+                Collections.singletonList("<a>; rel=foo"));
+        assertEquals("a", lhfp.getFirstTargetForRelation("foo"));
+    }
+
+    public void testMulti() {
+        LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser(
+                Collections.singletonList("<a>; rel=foo, <b>; rel=bar"));
+        assertEquals("b", lhfp.getFirstTargetForRelation("bar"));
+    }
+
+    public void testMultiQs() {
+        LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser(
+                Collections
+                        .singletonList("<a,>; rel=\"fo\\\"o,\", <b,>; rel=bar"));
+        assertEquals("b,", lhfp.getFirstTargetForRelation("bar"));
+    }
+
+    public void testTruncated() {
+        LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser(
+                Collections.singletonList("<a,>; rel=\"x\\\""));
+        assertEquals("a,", lhfp.getFirstTargetForRelation("x\\"));
+    }
+
+    public void testCommas() {
+        LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser(
+                Collections.singletonList(",<a>; rel=\"xy,z\","));
+        assertEquals("a", lhfp.getFirstTargetForRelation("xy,z"));
+    }
+
+    public void testMultiRel() {
+        LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser(
+                Collections.singletonList(",<a>; rel=\"a b\""));
+        assertEquals("a", lhfp.getFirstTargetForRelation("a"));
+    }
+}

Modified: jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java?rev=1200319&r1=1200318&r2=1200319&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java
(original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java
Thu Nov 10 13:11:53 2011
@@ -32,7 +32,8 @@ public class TestAll extends TestCase {
     public static Test suite() {
         TestSuite suite = new TestSuite("org.apache.jackrabbit.webdav.util tests");
 
-        suite.addTestSuite(CSRFUtilTest.class);
+........suite.addTestSuite(CSRFUtilTest.class);
+........suite.addTestSuite(LinkHeaderFieldParserTest.class);
 
         return suite;
     }



Mime
View raw message