You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by re...@apache.org on 2011/11/17 13:47:59 UTC
svn commit: r1203173 - in /jackrabbit/trunk:
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/
jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/
jackrab...
Author: reschke
Date: Thu Nov 17 12:47:58 2011
New Revision: 1203173
URL: http://svn.apache.org/viewvc?rev=1203173&view=rev
Log:
JCR-2542: spi2dav: EventFilters not respected
- spi.commons extension interface for Session extension
- noLocal flag support
- client sends session identifier (in Link header field) on write operations so that POLL can compute the flag
- SUBSCRIBE returns flags indicating extension features
Added:
jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionExtensions.java
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/repository.properties
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-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java
jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java
jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml
jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AdditionalEventInfo.java
jackrabbit/trunk/jackrabbit-spi2dav/pom.xml
jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventImpl.java
jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SessionInfoImpl.java
jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java
jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java
jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java
jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Thu Nov 17 12:47:58 2011
@@ -94,6 +94,7 @@ import org.apache.jackrabbit.core.xml.Im
import org.apache.jackrabbit.core.xml.SessionImporter;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.commons.SessionExtensions;
import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
import org.apache.jackrabbit.spi.commons.conversion.IdentifierResolver;
import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
@@ -111,7 +112,7 @@ import org.xml.sax.ContentHandler;
* A <code>SessionImpl</code> ...
*/
public class SessionImpl extends AbstractSession
- implements JackrabbitSession, NamespaceResolver, NamePathResolver, IdentifierResolver {
+ implements JackrabbitSession, SessionExtensions, NamespaceResolver, NamePathResolver, IdentifierResolver {
/**
* Name of the session attribute that controls whether the
@@ -510,7 +511,7 @@ public class SessionImpl extends Abstrac
* @param value attribute value
* @since Apache Jackrabbit 1.6
*/
- protected void setAttribute(String name, Object value) {
+ public void setAttribute(String name, Object value) {
if (value != null) {
attributes.put(name, value);
} else {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java Thu Nov 17 12:47:58 2011
@@ -223,6 +223,8 @@ public final class EventImpl implements
return eventState.isExternal();
}
+ //---------------------------------------------------------------< AdditionalEventInfo >
+
/**
* @return the primary node type of the node associated with the event
* @see AdditionalEventInfo#getPrimaryNodeTypeName()
@@ -230,7 +232,7 @@ public final class EventImpl implements
public Name getPrimaryNodeTypeName() {
return eventState.getNodeType();
}
-
+
/**
* @return the mixin node types of the node associated with the event
* @see AdditionalEventInfo#getMixinTypeNames()
@@ -240,6 +242,13 @@ public final class EventImpl implements
}
/**
+ * @return the specified session attribute
+ */
+ public Object getSessionAttribute(String name) {
+ return eventState.getSession().getAttribute(name);
+ }
+
+ /**
* Returns a String representation of this <code>Event</code>.
*
* @return a String representation of this <code>Event</code>.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/repository.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/repository.properties?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/repository.properties (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/repository.properties Thu Nov 17 12:47:58 2011
@@ -35,3 +35,6 @@ jcr.repository.name = Jackrabbit
# The descriptor for the version of this repository implementation.
jcr.repository.version = ${pom.version}
+
+# The repository supports the AdditionalEventInfo extension
+org.apache.jackrabbit.spi.commons.AdditionalEventInfo = true
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=1203173&r1=1203172&r2=1203173&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 17 12:47:58 2011
@@ -154,7 +154,7 @@ public interface JcrRemotingConstants {
/**
* RFC 5988 relation type for user data
* <p>
- * We transport JCR User Data in a Link header field with this relation name
+ * Used to transport JCR User Data inside an HTTP request.
* <p>
* Example:
*
@@ -163,4 +163,17 @@ public interface JcrRemotingConstants {
* </pre>
*/
public static final String RELATION_USER_DATA = NS_URI + "/user-data";
+
+ /**
+ * RFC 5988 relation type for remote session identification
+ * <p>
+ * Used to transport an identifier for the remote session.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * Link: <urn:uuid:96d3c6fe-1073-11e1-a3c0-00059a3c7a00>, rel="<i>RELATION_REMOTE_SESSION_ID</i>"
+ * </pre>
+ */
+ public static final String RELATION_REMOTE_SESSION_ID = NS_URI + "/session-id";
}
\ 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=1203173&r1=1203172&r2=1203173&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 17 12:47:58 2011
@@ -18,7 +18,6 @@ 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;
@@ -30,6 +29,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants;
+import org.apache.jackrabbit.spi.commons.SessionExtensions;
import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.webdav.util.LinkHeaderFieldParser;
@@ -38,6 +38,8 @@ import org.apache.jackrabbit.webdav.util
*/
public class SessionProviderImpl implements SessionProvider {
+ public static final String ATTRIBUTE_SESSION_ID = SessionProviderImpl.class + "#sessionid()";
+
/**
* the credentials provider
*/
@@ -65,8 +67,18 @@ public class SessionProviderImpl impleme
} else {
s = repository.login(creds, workspace);
}
- String userData = getJcrUserData(request);
+
+ // extract information from Link header fields
+ LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser(
+ request.getHeaders("Link"));
+ String userData = getJcrUserData(lhfp);
s.getWorkspace().getObservationManager().setUserData(userData);
+
+ String sessionId = getSessionIdentifier(lhfp);
+ if (s instanceof SessionExtensions) {
+ SessionExtensions xs = (SessionExtensions) s;
+ xs.setAttribute(ATTRIBUTE_SESSION_ID, sessionId);
+ }
return s;
}
@@ -78,20 +90,23 @@ public class SessionProviderImpl impleme
}
// find first link relation for JCR User Data
- private String getJcrUserData(HttpServletRequest request) {
+ private String getJcrUserData(LinkHeaderFieldParser lhfp) {
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);
- }
+ String target = lhfp
+ .getFirstTargetForRelation(JcrRemotingConstants.RELATION_USER_DATA);
+ if (target != null) {
+ jcrUserData = getJcrUserData(target);
}
+
return jcrUserData;
}
+ // find first link relation for remote session identifier
+ private String getSessionIdentifier(LinkHeaderFieldParser lhfp) {
+ return lhfp
+ .getFirstTargetForRelation(JcrRemotingConstants.RELATION_REMOTE_SESSION_ID);
+ }
+
// extracts User Data string from RFC 2397 "data" URI
// only supports the simple case of "data:,..." for now
private String getJcrUserData(String target) {
Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java Thu Nov 17 12:47:58 2011
@@ -17,8 +17,11 @@
package org.apache.jackrabbit.webdav.jcr.observation;
import org.apache.jackrabbit.commons.webdav.EventUtil;
+import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants;
+import org.apache.jackrabbit.server.SessionProviderImpl;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.commons.AdditionalEventInfo;
+import org.apache.jackrabbit.spi.commons.SessionExtensions;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavResourceLocator;
import org.apache.jackrabbit.webdav.DavServletResponse;
@@ -42,8 +45,12 @@ import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import com.sun.org.apache.xalan.internal.xsltc.dom.ExtendedSAX;
+
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
@@ -73,6 +80,7 @@ public class SubscriptionImpl implements
private final String subscriptionId = UUID.randomUUID().toString();
private final List<EventBundle> eventBundles = new ArrayList<EventBundle>();
private final ObservationManager obsMgr;
+ private final Session session;
/**
* Create a new <code>Subscription</code> with the given {@link SubscriptionInfo}
@@ -87,9 +95,9 @@ public class SubscriptionImpl implements
throws DavException {
setInfo(info);
locator = resource.getLocator();
- Session s = JcrDavSession.getRepositorySession(resource.getSession());
+ session = JcrDavSession.getRepositorySession(resource.getSession());
try {
- obsMgr = s.getWorkspace().getObservationManager();
+ obsMgr = session.getWorkspace().getObservationManager();
} catch (RepositoryException e) {
throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
@@ -105,6 +113,15 @@ public class SubscriptionImpl implements
return subscriptionId;
}
+ public boolean eventsProvideNodeTypeInformation() {
+ String t = session.getRepository().getDescriptor("org.apache.jackrabbit.spi.commons.AdditionalEventInfo");
+ return t == null ? false : Boolean.parseBoolean(t);
+ }
+
+ public boolean eventsProvideNoLocalFlag() {
+ return session instanceof SessionExtensions;
+ }
+
//----------------------------------------------------< XmlSerializable >---
/**
* Return the Xml representation of this <code>Subscription</code> as required
@@ -127,6 +144,12 @@ public class SubscriptionImpl implements
Element id = DomUtil.addChildElement(subscr, XML_SUBSCRIPTIONID, NAMESPACE);
id.appendChild(DomUtil.hrefToXml(getSubscriptionId(), document));
}
+
+ DomUtil.addChildElement(subscr, XML_EVENTSWITHTYPES, NAMESPACE,
+ Boolean.toString(eventsProvideNodeTypeInformation()));
+ DomUtil.addChildElement(subscr, XML_EVENTSWITHLOCALFLAG, NAMESPACE,
+ Boolean.toString(eventsProvideNoLocalFlag()));
+
return subscr;
}
@@ -430,11 +453,37 @@ public class SubscriptionImpl implements
public Element toXml(Document document) {
Element bundle = DomUtil.createElement(document, XML_EVENTBUNDLE, NAMESPACE);
+ // TODO: this appears to be unused now
if (transactionId != null) {
DomUtil.setAttribute(bundle, XML_EVENT_TRANSACTION_ID, NAMESPACE, transactionId);
}
+
+ boolean localFlagSet = false;
+
while (events.hasNext()) {
Event event = events.nextEvent();
+
+ if (!localFlagSet) {
+ // obtain remote session identifier
+ localFlagSet = true;
+ String forSessionId = (String) session
+ .getAttribute(SessionProviderImpl.ATTRIBUTE_SESSION_ID);
+ // calculate "local" flags
+ if (forSessionId != null
+ && event instanceof AdditionalEventInfo) {
+ try {
+ String eventforSessionId = (String) ((AdditionalEventInfo) event)
+ .getSessionAttribute(SessionProviderImpl.ATTRIBUTE_SESSION_ID);
+ boolean isLocal = forSessionId
+ .equals(eventforSessionId);
+ DomUtil.setAttribute(bundle, XML_EVENT_LOCAL,
+ NAMESPACE, Boolean.toString(isLocal));
+ } catch (UnsupportedRepositoryOperationException ex) {
+ // optional feature
+ }
+ }
+ }
+
Element eventElem = DomUtil.addChildElement(bundle, XML_EVENT, NAMESPACE);
// href
String eHref = "";
@@ -452,12 +501,21 @@ public class SubscriptionImpl implements
// user id
DomUtil.addChildElement(eventElem, XML_EVENTUSERID, NAMESPACE, event.getUserID());
+ // try to compute nodetype information
if (event instanceof AdditionalEventInfo) {
- DomUtil.addChildElement(eventElem, "primarynodetype", NAMESPACE,
- ((AdditionalEventInfo)event).getPrimaryNodeTypeName().toString());
- for (Name mixin : ((AdditionalEventInfo)event).getMixinTypeNames()) {
- DomUtil.addChildElement(eventElem, "mixinnodetype", NAMESPACE,
- mixin.toString());
+ try {
+ DomUtil.addChildElement(eventElem,
+ XML_EVENTPRIMARNODETYPE, NAMESPACE,
+ ((AdditionalEventInfo) event)
+ .getPrimaryNodeTypeName().toString());
+ for (Name mixin : ((AdditionalEventInfo) event)
+ .getMixinTypeNames()) {
+ DomUtil.addChildElement(eventElem,
+ XML_EVENTPRIMARNODETYPE, NAMESPACE,
+ mixin.toString());
+ }
+ } catch (UnsupportedRepositoryOperationException ex) {
+ // optional
}
}
Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java Thu Nov 17 12:47:58 2011
@@ -288,6 +288,14 @@ public class SubscriptionManagerImpl imp
public Element toXml(Document document) {
return delegatee.toXml(document);
}
+
+ public boolean eventsProvideNodeTypeInformation() {
+ return delegatee.eventsProvideNodeTypeInformation();
+ }
+
+ public boolean eventsProvideNoLocalFlag() {
+ return delegatee.eventsProvideNoLocalFlag();
+ }
}
/**
Modified: jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml (original)
+++ jackrabbit/trunk/jackrabbit-jcr2dav/pom.xml Thu Nov 17 12:47:58 2011
@@ -80,8 +80,6 @@
org.apache.jackrabbit.test.api.observation.GetIdentifierTest#testNodeRemoved
<!-- JCR-2541 : event journal -->
org.apache.jackrabbit.test.api.observation.EventJournalTest
- <!-- JCR-2542 : event filter -->
- org.apache.jackrabbit.test.api.observation.AddEventListenerTest#testNoLocalTrue
<!-- JCR-2533 : missing impl of checkQueryStatement -->
org.apache.jackrabbit.test.api.query.CreateQueryTest#testUnknownQueryLanguage
<!-- JCR-2543 : query offset -->
Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AdditionalEventInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AdditionalEventInfo.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AdditionalEventInfo.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AdditionalEventInfo.java Thu Nov 17 12:47:58 2011
@@ -18,6 +18,8 @@ package org.apache.jackrabbit.spi.common
import java.util.Set;
+import javax.jcr.UnsupportedRepositoryOperationException;
+
import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.Name;
@@ -29,10 +31,15 @@ public interface AdditionalEventInfo {
/**
* @return the name of the primary node type of the node associated with the event
*/
- public Name getPrimaryNodeTypeName();
-
+ public Name getPrimaryNodeTypeName() throws UnsupportedRepositoryOperationException;
+
/**
* @return the names of the mixin node types of the node associated with the event
*/
- public Set<Name> getMixinTypeNames();
+ public Set<Name> getMixinTypeNames() throws UnsupportedRepositoryOperationException;
+
+ /**
+ * @return the specified Session attribute
+ */
+ public Object getSessionAttribute(String name) throws UnsupportedRepositoryOperationException;
}
Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionExtensions.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionExtensions.java?rev=1203173&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionExtensions.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionExtensions.java Thu Nov 17 12:47:58 2011
@@ -0,0 +1,32 @@
+/*
+ * 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.spi.commons;
+
+import javax.jcr.Session;
+
+/**
+ * Provides additional methods for {@link Session} access..
+ */
+public interface SessionExtensions {
+
+ /**
+ * Sets the specified {@link Session} attribute.
+ * @param name attribute name
+ * @param value attribute value
+ */
+ public void setAttribute(String name, Object value);
+}
Modified: jackrabbit/trunk/jackrabbit-spi2dav/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/pom.xml?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/pom.xml (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/pom.xml Thu Nov 17 12:47:58 2011
@@ -77,8 +77,6 @@
org.apache.jackrabbit.test.api.observation.GetIdentifierTest#testNodeRemoved
<!-- JCR-2541 : event journal -->
org.apache.jackrabbit.test.api.observation.EventJournalTest
- <!-- JCR-2542 : event filter -->
- org.apache.jackrabbit.test.api.observation.AddEventListenerTest#testNoLocalTrue
<!-- JCR-2533 : missing impl of checkQueryStatement -->
org.apache.jackrabbit.test.api.query.CreateQueryTest#testUnknownQueryLanguage
<!-- JCR-2543 : query offset -->
Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventImpl.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventImpl.java Thu Nov 17 12:47:58 2011
@@ -57,15 +57,22 @@ public class EventImpl
private static final NameFactory N_FACTORY = NameFactoryImpl.getInstance();
- public EventImpl(ItemId eventId, Path eventPath, NodeId parentId, int eventType,
- Element eventElement, NamePathResolver resolver, QValueFactory qvFactory) throws NamespaceException, IllegalNameException {
+ public EventImpl(ItemId eventId, Path eventPath, NodeId parentId,
+ int eventType, Element eventElement, NamePathResolver resolver,
+ QValueFactory qvFactory) throws NamespaceException,
+ IllegalNameException {
super(getSpiEventType(eventType), eventPath, eventId, parentId,
- resolver.getQName(DomUtil.getChildTextTrim(eventElement, "primarynodetype", NAMESPACE)),
- getNames(DomUtil.getChildren(eventElement, "mixinnodetype", NAMESPACE), resolver),
- DomUtil.getChildTextTrim(eventElement, XML_EVENTUSERID, NAMESPACE),
- DomUtil.getChildTextTrim(eventElement, XML_EVENTUSERDATA, NAMESPACE),
- Long.parseLong(DomUtil.getChildTextTrim(eventElement, XML_EVENTDATE, NAMESPACE)),
- getEventInfo(DomUtil.getChildElement(eventElement, XML_EVENTINFO, NAMESPACE), resolver, qvFactory));
+ resolver.getQName(DomUtil.getChildTextTrim(eventElement,
+ XML_EVENTPRIMARNODETYPE, NAMESPACE)), getNames(
+ DomUtil.getChildren(eventElement,
+ XML_EVENTMIXINNODETYPE, NAMESPACE), resolver),
+ DomUtil.getChildTextTrim(eventElement, XML_EVENTUSERID,
+ NAMESPACE), DomUtil.getChildTextTrim(eventElement,
+ XML_EVENTUSERDATA, NAMESPACE), Long.parseLong(DomUtil
+ .getChildTextTrim(eventElement, XML_EVENTDATE,
+ NAMESPACE)), getEventInfo(
+ DomUtil.getChildElement(eventElement, XML_EVENTINFO,
+ NAMESPACE), resolver, qvFactory));
}
//--------------------------------------------------------------------------
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=1203173&r1=1203172&r2=1203173&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 17 12:47:58 2011
@@ -171,6 +171,7 @@ import org.apache.jackrabbit.webdav.obse
import org.apache.jackrabbit.webdav.observation.EventDiscovery;
import org.apache.jackrabbit.webdav.observation.EventType;
import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery;
import org.apache.jackrabbit.webdav.observation.SubscriptionInfo;
import org.apache.jackrabbit.webdav.ordering.OrderingConstants;
import org.apache.jackrabbit.webdav.property.DavProperty;
@@ -245,6 +246,10 @@ public class RepositoryServiceImpl imple
private final Map<String, QValue[]> descriptors =
new HashMap<String, QValue[]>();
+ /** Observation features. */
+ private boolean remoteServerProvidesNodeTypes = false;
+ private boolean remoteServerProvidesNoLocalFlag = false;
+
/**
* Same as {@link #RepositoryServiceImpl(String, IdFactory, NameFactory, PathFactory, QValueFactory, int, int)}
* using {@link ItemInfoCacheImpl#DEFAULT_CACHE_SIZE)} as size for the item
@@ -376,22 +381,52 @@ public class RepositoryServiceImpl imple
method.setRequestHeader(ifH.getHeaderName(), ifH.getHeaderValue());
}
}
+
+ initMethod(method, sessionInfo);
+ }
+
+ // set of HTTP methods that will not change the remote state
+ private static final Set<String> readMethods;
+ static {
+ Set<String> tmp = new HashSet<String>();
+ tmp.add("GET");
+ tmp.add("HEAD");
+ tmp.add("PROPFIND");
+ tmp.add("POLL");
+ tmp.add("REPORT");
+ tmp.add("SEARCH");
+ readMethods = Collections.unmodifiableSet(tmp);
+ }
+
+ // set headers for user data and session identification
+ protected static void initMethod(HttpMethod method, SessionInfo sessionInfo) throws RepositoryException {
+
+ boolean isReadAccess = readMethods.contains(method.getName());
+ boolean needsSessionId = !isReadAccess || "POLL".equals(method.getName());
+
+ if (sessionInfo instanceof SessionInfoImpl && needsSessionId) {
+ StringBuilder linkHeaderField = new StringBuilder();
+
+ String sessionIdentifier = ((SessionInfoImpl) sessionInfo)
+ .getSessionIdentifier();
+ linkHeaderField.append("<" + sessionIdentifier + ">; rel=\""
+ + JcrRemotingConstants.RELATION_REMOTE_SESSION_ID + "\"");
- if (sessionInfo instanceof SessionInfoImpl) {
String userdata = ((SessionInfoImpl) sessionInfo).getUserData();
- if (userdata != null) {
+ if (userdata != null && ! isReadAccess) {
String escaped = Text.escape(userdata);
- method.addRequestHeader("Link", "<data:," + escaped
- + ">; rel=\"" + JcrRemotingConstants.RELATION_USER_DATA
- + "\"");
+ linkHeaderField.append((", <data:," + escaped + ">; rel=\""
+ + JcrRemotingConstants.RELATION_USER_DATA + "\""));
}
+
+ method.addRequestHeader("Link", linkHeaderField.toString());
}
}
private static void initMethod(DavMethod method, BatchImpl batchImpl, boolean addIfHeader) throws RepositoryException {
initMethod(method, batchImpl.sessionInfo, addIfHeader);
- // add batchId as separate header
+ // add batchId as separate header, TODO: could probably re-use session id Link relation
CodedUrlHeader ch = new CodedUrlHeader(TransactionConstants.HEADER_TRANSACTIONID, batchImpl.batchId);
method.setRequestHeader(ch.getHeaderName(), ch.getHeaderValue());
}
@@ -1254,7 +1289,7 @@ public class RepositoryServiceImpl imple
} else if (ct.startsWith("text/xml")) {
// jcr:values property spooled
values = getValues(method.getResponseBodyAsStream(), resolver, propertyId);
- type = (values.length > 0) ? values[0].getType() : loadType(uri, client, propertyId, resolver);
+ type = (values.length > 0) ? values[0].getType() : loadType(uri, client, propertyId, sessionInfo, resolver);
isMultiValued = true;
} else {
throw new ItemNotFoundException("Unable to retrieve the property with id " + saveGetIdString(propertyId, resolver));
@@ -1312,7 +1347,7 @@ public class RepositoryServiceImpl imple
}
}
- private int loadType(String propertyURI, HttpClient client, PropertyId propertyId, NamePathResolver resolver) throws IOException, DavException, RepositoryException {
+ private int loadType(String propertyURI, HttpClient client, PropertyId propertyId, SessionInfo sessionInfo, NamePathResolver resolver) throws IOException, DavException, RepositoryException {
DavPropertyNameSet nameSet = new DavPropertyNameSet();
nameSet.add(JcrRemotingConstants.JCR_TYPE_LN, ItemResourceConstants.NAMESPACE);
@@ -2001,11 +2036,19 @@ public class RepositoryServiceImpl imple
public Subscription createSubscription(SessionInfo sessionInfo,
EventFilter[] filters)
throws UnsupportedRepositoryOperationException, RepositoryException {
- checkEventFilterSupport(filters);
+
checkSessionInfo(sessionInfo);
String rootUri = uriResolver.getRootItemUri(sessionInfo.getWorkspaceName());
String subscriptionId = subscribe(rootUri, S_INFO, null, sessionInfo, null);
log.debug("Subscribed on server for session info " + sessionInfo);
+
+ try {
+ checkEventFilterSupport(filters);
+ }
+ catch (UnsupportedRepositoryOperationException ex) {
+ unsubscribe(rootUri, subscriptionId, sessionInfo);
+ throw (ex);
+ }
return new EventSubscriptionImpl(subscriptionId, (SessionInfoImpl) sessionInfo);
}
@@ -2021,13 +2064,19 @@ public class RepositoryServiceImpl imple
checkEventFilterSupport(filters);
}
- private void checkEventFilterSupport(EventFilter[] filters) throws UnsupportedRepositoryOperationException {
+ private void checkEventFilterSupport(EventFilter[] filters)
+ throws UnsupportedRepositoryOperationException {
for (EventFilter ef : filters) {
if (ef instanceof EventFilterImpl) {
- EventFilterImpl efi = (EventFilterImpl)ef;
- // TODO: add code that verifies that the remote server can send node type information
- if (efi.getNoLocal()) {
- throw new UnsupportedRepositoryOperationException("This SPI implementation does not support filtering using the 'noLocal' flag (see issue JCR-2542)");
+ EventFilterImpl efi = (EventFilterImpl) ef;
+ if (efi.getNodeTypeNames() != null
+ && !remoteServerProvidesNodeTypes) {
+ throw new UnsupportedRepositoryOperationException(
+ "Remote server does not provide node type information in events");
+ }
+ if (efi.getNoLocal() && !remoteServerProvidesNoLocalFlag) {
+ throw new UnsupportedRepositoryOperationException(
+ "Remote server does not provide local flag in events");
}
}
}
@@ -2051,6 +2100,7 @@ public class RepositoryServiceImpl imple
} else {
method = new SubscribeMethod(uri, subscriptionInfo);
}
+ initMethod(method, sessionInfo);
if (batchId != null) {
// add batchId as separate header
@@ -2060,6 +2110,13 @@ public class RepositoryServiceImpl imple
getClient(sessionInfo).executeMethod(method);
method.checkSuccess();
+
+ org.apache.jackrabbit.webdav.observation.Subscription[] subs = method.getResponseAsSubscriptionDiscovery().getValue();
+ if (subs.length == 1) {
+ this.remoteServerProvidesNodeTypes = subs[0].eventsProvideNodeTypeInformation();
+ this.remoteServerProvidesNoLocalFlag = subs[0].eventsProvideNoLocalFlag();
+ }
+
return method.getSubscriptionId();
} catch (IOException e) {
throw new RepositoryException(e);
@@ -2076,6 +2133,7 @@ public class RepositoryServiceImpl imple
UnSubscribeMethod method = null;
try {
method = new UnSubscribeMethod(uri, subscriptionId);
+ initMethod(method, sessionInfo);
getClient(sessionInfo).executeMethod(method);
method.checkSuccess();
} catch (IOException e) {
@@ -2121,12 +2179,12 @@ public class RepositoryServiceImpl imple
while (it.hasNext()) {
Element bundleElement = it.nextElement();
String value = DomUtil.getAttribute(bundleElement,
- ObservationConstants.XML_EVENT_TRANSACTION_ID,
+ ObservationConstants.XML_EVENT_LOCAL,
ObservationConstants.NAMESPACE);
// check if it matches a batch id recently submitted
boolean isLocal = false;
if (value != null) {
- isLocal = value.equals(sessionInfo.getLastBatchId());
+ isLocal = Boolean.parseBoolean(value);
}
bundles.add(new EventBundleImpl(
buildEventList(bundleElement, sessionInfo),
Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SessionInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SessionInfoImpl.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SessionInfoImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SessionInfoImpl.java Thu Nov 17 12:47:58 2011
@@ -21,6 +21,7 @@ import org.apache.jackrabbit.spi.commons
import java.util.HashSet;
import java.util.Set;
import java.util.Arrays;
+import java.util.UUID;
/**
* <code>SessionInfoImpl</code>...
@@ -29,7 +30,10 @@ public class SessionInfoImpl extends org
private final CredentialsWrapper credentials;
private final Set<String> sessionScopedTokens = new HashSet<String>();
-
+
+ // a globally unique URI identifiying this session
+ private final String sessionIdentifier = "urn:uuid" + UUID.randomUUID();
+
private String lastBatchId;
private NamePathResolver resolver;
@@ -54,6 +58,10 @@ public class SessionInfoImpl extends org
return credentials;
}
+ String getSessionIdentifier() {
+ return sessionIdentifier;
+ }
+
/**
* Returns the id of the most recently submitted batch or <code>null</code>
* it no batch has been submitted yet.
Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java Thu Nov 17 12:47:58 2011
@@ -61,18 +61,23 @@ public interface ObservationConstants {
public static final String XML_NOLOCAL = "nolocal";
public static final String XML_FILTER = "filter";
public static final String XML_SUBSCRIPTIONID = "subscriptionid";
+ public static final String XML_EVENTSWITHTYPES = "eventswithnodetypes";
+ public static final String XML_EVENTSWITHLOCALFLAG = "eventswithlocalflag";
public static final String XML_UUID = "uuid";
public static final String XML_NODETYPE_NAME = "nodetype-name";
public static final String XML_EVENTDISCOVERY = "eventdiscovery";
public static final String XML_EVENTBUNDLE = "eventbundle";
public static final String XML_EVENT_TRANSACTION_ID = "transactionid";
+ public static final String XML_EVENT_LOCAL = "local";
public static final String XML_EVENT = "event";
public static final String XML_EVENTUSERID = "eventuserid";
public static final String XML_EVENTUSERDATA = "eventuserdata";
public static final String XML_EVENTDATE = "eventdate";
public static final String XML_EVENTIDENTIFIER = "eventidentifier";
public static final String XML_EVENTINFO = "eventinfo";
+ public static final String XML_EVENTPRIMARNODETYPE = "eventprimarynodetype";
+ public static final String XML_EVENTMIXINNODETYPE = "eventmixinnodetype";
//---< Property Names >-----------------------------------------------------
/**
Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java Thu Nov 17 12:47:58 2011
@@ -36,4 +36,14 @@ public interface Subscription extends Xm
* @return subscriptionId
*/
public String getSubscriptionId();
+
+ /**
+ * @return whether events will be returned with node type information
+ */
+ public boolean eventsProvideNodeTypeInformation();
+
+ /**
+ * @return whether events will be returned with the "noLocal" flag
+ */
+ public boolean eventsProvideNoLocalFlag();
}
\ No newline at end of file
Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java?rev=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java Thu Nov 17 12:47:58 2011
@@ -113,6 +113,17 @@ public class SubscriptionDiscovery exten
}
return null;
}
+
+ public boolean eventsProvideNodeTypeInformation() {
+ String t = DomUtil.getChildText(sb, ObservationConstants.XML_EVENTSWITHTYPES, ObservationConstants.NAMESPACE);
+ return t == null ? false : Boolean.parseBoolean(t);
+ }
+
+ public boolean eventsProvideNoLocalFlag() {
+ String t = DomUtil.getChildText(sb, ObservationConstants.XML_EVENTSWITHLOCALFLAG, ObservationConstants.NAMESPACE);
+ return t == null ? false : Boolean.parseBoolean(t);
+ }
+
/**
* @see XmlSerializable#toXml(Document)
*/
Modified: 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=1203173&r1=1203172&r2=1203173&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java Thu Nov 17 12:47:58 2011
@@ -57,13 +57,18 @@ public class LinkHeaderFieldParser {
public LinkHeaderFieldParser(Enumeration<?> en) {
- List<LinkRelation> tmp = new ArrayList<LinkRelation>();
+ if (en.hasMoreElements()) {
+ List<LinkRelation> tmp = new ArrayList<LinkRelation>();
- while (en.hasMoreElements()) {
- addFields(tmp, en.nextElement().toString());
- }
+ while (en.hasMoreElements()) {
+ addFields(tmp, en.nextElement().toString());
+ }
- relations = Collections.unmodifiableList(tmp);
+ relations = Collections.unmodifiableList(tmp);
+ } else {
+ // optimize case of no Link headers
+ relations = Collections.emptyList();
+ }
}
public String getFirstTargetForRelation(String relationType) {