You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2006/09/29 16:44:40 UTC
svn commit: r451313 [2/2] - in /jackrabbit/trunk/contrib/spi:
jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/
jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/
jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/
jcr2spi/src/ma...
Modified: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java?view=diff&rev=451313&r1=451312&r2=451313
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java Fri Sep 29 07:44:39 2006
@@ -20,13 +20,11 @@
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
-import org.apache.commons.httpclient.UsernamePasswordCredentials;
-import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
-import org.apache.commons.collections.map.LRUMap;
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
import org.apache.jackrabbit.webdav.property.DavPropertySet;
import org.apache.jackrabbit.webdav.property.DavPropertyName;
@@ -58,15 +56,20 @@
import org.apache.jackrabbit.webdav.client.methods.DavMethod;
import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
import org.apache.jackrabbit.webdav.client.methods.MergeMethod;
+import org.apache.jackrabbit.webdav.client.methods.SubscribeMethod;
+import org.apache.jackrabbit.webdav.client.methods.UnSubscribeMethod;
+import org.apache.jackrabbit.webdav.client.methods.PollMethod;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.MultiStatusResponse;
import org.apache.jackrabbit.webdav.DavServletResponse;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.MultiStatus;
+import org.apache.jackrabbit.webdav.DavMethods;
import org.apache.jackrabbit.webdav.observation.SubscriptionInfo;
import org.apache.jackrabbit.webdav.observation.EventType;
import org.apache.jackrabbit.webdav.observation.Filter;
import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+import org.apache.jackrabbit.webdav.observation.EventDiscovery;
import org.apache.jackrabbit.webdav.security.SecurityConstants;
import org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty;
import org.apache.jackrabbit.webdav.security.Privilege;
@@ -91,9 +94,7 @@
import org.apache.jackrabbit.webdav.jcr.property.NamespacesProperty;
import org.apache.jackrabbit.webdav.jcr.observation.SubscriptionImpl;
import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants;
-import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.name.NoPrefixDeclaredException;
-import org.apache.jackrabbit.name.NamespaceResolver;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.name.NameFormat;
import org.apache.jackrabbit.spi.Batch;
@@ -115,6 +116,7 @@
import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.IdFactory;
import org.apache.jackrabbit.spi.LockInfo;
+import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.uuid.UUID;
import org.apache.jackrabbit.value.ValueFormat;
import org.apache.jackrabbit.value.QValue;
@@ -138,7 +140,6 @@
import javax.jcr.PropertyType;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
-import javax.jcr.SimpleCredentials;
import javax.jcr.LoginException;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
@@ -153,6 +154,7 @@
import java.util.HashSet;
import java.util.Set;
import java.util.Collection;
+import java.util.HashMap;
import java.util.Collections;
import java.io.InputStream;
import java.io.IOException;
@@ -162,12 +164,24 @@
*/
// TODO: encapsulate URI building, escaping, unescaping...
// TODO: cache info objects
-// TODO: improve handling of HttpClient
// TODO: TO-BE-FIXED. caches don't get adjusted upon removal/move of items
public class RepositoryServiceImpl implements RepositoryService, DavConstants {
private static Logger log = LoggerFactory.getLogger(RepositoryServiceImpl.class);
+
+ private static final EventType[] ALL_EVENTS = new EventType[5];
+ static {
+ ALL_EVENTS[0] = SubscriptionImpl.getEventType(javax.jcr.observation.Event.NODE_ADDED);
+ ALL_EVENTS[1] = SubscriptionImpl.getEventType(javax.jcr.observation.Event.NODE_REMOVED);
+ ALL_EVENTS[2] = SubscriptionImpl.getEventType(javax.jcr.observation.Event.PROPERTY_ADDED);
+ ALL_EVENTS[3] = SubscriptionImpl.getEventType(javax.jcr.observation.Event.PROPERTY_CHANGED);
+ ALL_EVENTS[4] = SubscriptionImpl.getEventType(javax.jcr.observation.Event.PROPERTY_REMOVED);
+ }
+ private static final SubscriptionInfo S_INFO = new SubscriptionInfo(ALL_EVENTS, true, DavConstants.INFINITE_TIMEOUT);
+
+ private static long POLL_INTERVAL = 30000; // TODO: make configurable
+
private final IdFactory idFactory;
private final ValueFactory valueFactory;
@@ -175,9 +189,7 @@
private final NamespaceResolverImpl nsResolver;
private final URIResolverImpl uriResolver;
- private final HostConfiguration hostConfig;
- // remember most frequently used http clients
- private final Map clientCache = Collections.synchronizedMap(new LRUMap());
+ private final HttpClient client;
public RepositoryServiceImpl(String uri, IdFactory idFactory, ValueFactory valueFactory) throws RepositoryException {
if (uri == null || "".equals(uri)) {
@@ -190,61 +202,38 @@
this.valueFactory = valueFactory;
try {
+ domFactory = DomUtil.BUILDER_FACTORY.newDocumentBuilder().newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new RepositoryException(e);
+ }
+
+ try {
URI repositoryUri = new URI((uri.endsWith("/")) ? uri : uri+"/", true);
- hostConfig = new HostConfiguration();
+ HostConfiguration hostConfig = new HostConfiguration();
hostConfig.setHost(repositoryUri);
- domFactory = DomUtil.BUILDER_FACTORY.newDocumentBuilder().newDocument();
+ client = new HttpClient(new MultiThreadedHttpConnectionManager());
+ client.setHostConfiguration(hostConfig);
+ // always send authentication not waiting for 401
+ client.getParams().setAuthenticationPreemptive(true);
nsResolver = new NamespaceResolverImpl();
uriResolver = new URIResolverImpl(repositoryUri, this, nsResolver, domFactory);
} catch (URIException e) {
throw new RepositoryException(e);
- } catch (ParserConfigurationException e) {
- throw new RepositoryException(e);
}
}
- private HttpClient getClient(Credentials credentials) {
- if (clientCache.containsKey(credentials)) {
- return (HttpClient) clientCache.get(credentials);
- } else {
- HttpClient client = new HttpClient();
- client.setHostConfiguration(hostConfig);
- UsernamePasswordCredentials creds;
- if (credentials == null) {
- // NOTE: null credentials only work if 'missing-auth-mapping' param is set on the server
- creds = null;
- } else if (credentials instanceof SimpleCredentials) {
- SimpleCredentials sCred = (SimpleCredentials) credentials;
- creds = new UsernamePasswordCredentials(sCred.getUserID(),
- String.valueOf(sCred.getPassword()));
- } else {
- creds = new UsernamePasswordCredentials(credentials.toString());
- }
- HttpState httpState = client.getState();
-
- // set authentication scope and credentials
- AuthScope authscope = new AuthScope(hostConfig.getHost(), hostConfig.getPort());
- httpState.setCredentials(authscope, creds);
-
- // always send authentication not waiting for 401
- client.getParams().setAuthenticationPreemptive(true);
-
- clientCache.put(credentials, client);
- return client;
+ private static void checkSessionInfo(SessionInfo sessionInfo) throws RepositoryException {
+ if (!(sessionInfo instanceof SessionInfoImpl)) {
+ throw new RepositoryException("Unknown SessionInfo implementation.");
}
}
- HttpClient getClient(SessionInfo sessionInfo) {
- Credentials credentials = null;
- if (sessionInfo instanceof SessionInfoImpl) {
- credentials = ((SessionInfoImpl) sessionInfo).getCredentials();
- } else {
- log.warn("Unexpected SessionInfo implementation. Using 'null' credentials for connection.");
- }
- return getClient(credentials);
+ private static boolean isLockMethod(DavMethod method) {
+ int code = DavMethods.getMethodCode(method.getName());
+ return DavMethods.DAV_LOCK == code || DavMethods.DAV_UNLOCK == code;
}
private static void initMethod(DavMethod method, SessionInfo sessionInfo, boolean addIfHeader) {
@@ -256,47 +245,28 @@
method.setRequestHeader(ifH.getHeaderName(), ifH.getHeaderValue());
}
}
- if (sessionInfo instanceof SessionInfoImpl) {
- String txId = ((SessionInfoImpl) sessionInfo).getBatchId();
- if (txId != null) {
- CodedUrlHeader ch = new CodedUrlHeader(TransactionConstants.HEADER_TRANSACTIONID, txId);
- method.setRequestHeader(ch.getHeaderName(), ch.getHeaderValue());
- }
- }
- }
-
- private URIResolver getURIResolver() {
- return uriResolver;
}
- private NamespaceResolver getNamespaceResolver() {
- return nsResolver;
+ private HttpClient getClient(org.apache.commons.httpclient.Credentials credentials) {
+ // NOTE: null credentials only work if 'missing-auth-mapping' param is
+ // set on the server
+ client.getState().setCredentials(AuthScope.ANY, credentials);
+ return client;
}
- private String getRepositoryUri() {
- return uriResolver.getRepositoryUri();
- }
-
- private String getWorkspaceUri(String workspaceName) {
- return uriResolver.getWorkspaceUri(workspaceName);
- }
-
- private String getRootItemUri(String workspaceName) {
- return uriResolver.getRootItemUri(workspaceName);
+ HttpClient getClient(SessionInfo sessionInfo) throws RepositoryException {
+ checkSessionInfo(sessionInfo);
+ return getClient(((SessionInfoImpl) sessionInfo).getCredentials().getCredentials());
}
private String getItemUri(ItemId itemId, SessionInfo sessionInfo) throws RepositoryException {
return uriResolver.getItemUri(itemId, sessionInfo.getWorkspaceName(), sessionInfo);
}
- private String getItemUri(ItemId itemId, String workspaceName, SessionInfo sessionInfo) throws RepositoryException {
- return uriResolver.getItemUri(itemId, workspaceName, sessionInfo);
- }
-
private String getItemUri(NodeId parentId, QName childName, SessionInfo sessionInfo) throws RepositoryException {
String parentUri = uriResolver.getItemUri(parentId, sessionInfo.getWorkspaceName(), sessionInfo);
try {
- return parentUri + NameFormat.format(childName, getNamespaceResolver());
+ return parentUri + NameFormat.format(childName, nsResolver);
} catch (NoPrefixDeclaredException e) {
throw new RepositoryException(e);
}
@@ -309,7 +279,7 @@
HrefProperty parentProp = new HrefProperty(propSet.get(ItemResourceConstants.JCR_PARENT));
String parentHref = parentProp.getHrefs().get(0).toString();
if (parentHref != null && parentHref.length() > 0) {
- parentId = getURIResolver().getNodeId(parentHref, sessionInfo);
+ parentId = uriResolver.getNodeId(parentHref, sessionInfo);
}
}
return parentId;
@@ -317,9 +287,40 @@
//--------------------------------------------------------------------------
- private EventIterator retrieveEvents() {
- // todo
- return null;
+ /**
+ * Execute a 'Workspace' operation that immediately needs to return events.
+ *
+ * @param method
+ * @param sessionInfo
+ * @return
+ * @throws RepositoryException
+ */
+ private EventIterator execute(DavMethod method, SessionInfo sessionInfo) throws RepositoryException {
+ // TODO: build specific subscrUri
+ // TODO: check if 'all event' subscription is ok
+ String subscrUri = uriResolver.getRootItemUri(sessionInfo.getWorkspaceName());
+ String subscrId = subscribe(subscrUri, S_INFO, null, sessionInfo);
+ try {
+ if (isLockMethod(method)) {
+ initMethod(method, sessionInfo, false);
+ } else {
+ initMethod(method, sessionInfo, true);
+ }
+ getClient(sessionInfo).executeMethod(method);
+ method.checkSuccess();
+
+ EventIterator events = poll(subscrUri, subscrId, sessionInfo);
+ return events;
+ } catch (IOException e) {
+ throw new RepositoryException(e);
+ } catch (DavException e) {
+ throw ExceptionConverter.generate(e);
+ } finally {
+ if (method != null) {
+ method.releaseConnection();
+ }
+ unsubscribe(subscrUri, subscrId, sessionInfo);
+ }
}
@@ -338,9 +339,9 @@
ReportInfo info = new ReportInfo(RepositoryDescriptorsReport.REPOSITORY_DESCRIPTORS_REPORT, DavConstants.DEPTH_0);
ReportMethod method = null;
try {
- method = new ReportMethod(getRepositoryUri(), info);
+ method = new ReportMethod(uriResolver.getRepositoryUri(), info);
- getClient((Credentials) null).executeMethod(method);
+ getClient((org.apache.commons.httpclient.Credentials) null).executeMethod(method);
method.checkSuccess();
Document doc = method.getResponseBodyAsDocument();
Properties descriptors = new Properties();
@@ -376,30 +377,30 @@
*/
public SessionInfo login(Credentials credentials, String workspaceName)
throws LoginException, NoSuchWorkspaceException, RepositoryException {
- if (credentials == null) {
- // no credentials provided, use JAAS
- throw new RepositoryException("JAAS authentication not implemented");
- }
-
- // interested in workspace href property only, which allows to retrieve the
- // name of the workspace in case 'workspaceName' is 'null'.
- DavPropertyNameSet nameSet = new DavPropertyNameSet();
- nameSet.add(DeltaVConstants.WORKSPACE);
+ // check if the workspace with the given name is accessible
PropFindMethod method = null;
try {
- method = new PropFindMethod(getWorkspaceUri(workspaceName), nameSet, DavConstants.DEPTH_0);
- getClient(credentials).executeMethod(method);
+ DavPropertyNameSet nameSet = new DavPropertyNameSet();
+ nameSet.add(DeltaVConstants.WORKSPACE);
+ method = new PropFindMethod(uriResolver.getWorkspaceUri(workspaceName), nameSet, DavConstants.DEPTH_0);
+ CredentialsWrapper dc = new CredentialsWrapper(credentials);
+ getClient(dc.getCredentials()).executeMethod(method);
+
MultiStatusResponse[] responses = method.getResponseBodyAsMultiStatus().getResponses();
if (responses.length != 1) {
- throw new RepositoryException("Unable to retrieve default workspace name.");
+ throw new LoginException("Login failed: Unknown workspace '" + workspaceName+ " '.");
}
+
DavPropertySet props = responses[0].getProperties(DavServletResponse.SC_OK);
if (props.contains(DeltaVConstants.WORKSPACE)) {
String wspHref = new HrefProperty(props.get(DeltaVConstants.WORKSPACE)).getHrefs().get(0).toString();
- String wspName = Text.getName(wspHref, true);
- return new SessionInfoImpl(credentials, wspName);
+ String wspName = Text.unescape(Text.getName(wspHref, true));
+ if (!wspName.equals(workspaceName)) {
+ throw new LoginException("Login failed: Invalid workspace name " + workspaceName);
+ }
+ return new SessionInfoImpl(dc, workspaceName, new SubscriptionMgrImpl());
} else {
- throw new RepositoryException("Unable to retrieve default workspace name.");
+ throw new LoginException("Login failed: Unknown workspace '" + workspaceName+ " '.");
}
} catch (IOException e) {
throw new RepositoryException(e.getMessage());
@@ -420,7 +421,7 @@
nameSet.add(DeltaVConstants.WORKSPACE);
PropFindMethod method = null;
try {
- method = new PropFindMethod(getRepositoryUri(), nameSet, DEPTH_1);
+ method = new PropFindMethod(uriResolver.getRepositoryUri(), nameSet, DEPTH_1);
getClient(sessionInfo).executeMethod(method);
MultiStatusResponse[] responses = method.getResponseBodyAsMultiStatus().getResponses();
Set ids = new HashSet();
@@ -455,7 +456,7 @@
ReportInfo reportInfo = new ReportInfo(JcrPrivilegeReport.PRIVILEGES_REPORT);
reportInfo.setContentElement(DomUtil.hrefToXml(uri, domFactory));
- method = new ReportMethod(getWorkspaceUri(sessionInfo.getWorkspaceName()), reportInfo);
+ method = new ReportMethod(uriResolver.getWorkspaceUri(sessionInfo.getWorkspaceName()), reportInfo);
getClient(sessionInfo).executeMethod(method);
method.checkSuccess();
@@ -495,8 +496,8 @@
* @see RepositoryService#getRootId(SessionInfo)
*/
public NodeId getRootId(SessionInfo sessionInfo) throws RepositoryException {
- String rootUri = getRootItemUri(sessionInfo.getWorkspaceName());
- return getURIResolver().getNodeId(rootUri, sessionInfo);
+ String rootUri = uriResolver.getRootItemUri(sessionInfo.getWorkspaceName());
+ return uriResolver.getNodeId(rootUri, sessionInfo);
}
/**
@@ -534,21 +535,30 @@
MultiStatusResponse[] responses = method.getResponseBodyAsMultiStatus().getResponses();
if (responses.length < 1) {
- throw new ItemNotFoundException("Unable to retrieve the item with id " + itemId);
+ throw new ItemNotFoundException("Unable to retrieve the item definition for " + itemId);
+ }
+ if (responses.length > 1) {
+ throw new RepositoryException("Internal error: ambigous item definition found '" + itemId + "'.");
}
- // todo: make sure the server only sent a single response...
- // todo: make sure the resourcetype matches the itemId type
- QItemDefinition definition = null;
DavPropertySet propertySet = responses[0].getProperties(DavServletResponse.SC_OK);
+
+ // check if definition matches the type of the id
+ DavProperty rType = propertySet.get(DavPropertyName.RESOURCETYPE);
+ if (rType.getValue() == null && itemId.denotesNode()) {
+ throw new RepositoryException("Internal error: requested node definition and got property definition.");
+ }
+
+ // build the definition
+ QItemDefinition definition = null;
if (propertySet.contains(ItemResourceConstants.JCR_DEFINITION)) {
DavProperty prop = propertySet.get(ItemResourceConstants.JCR_DEFINITION);
Object value = prop.getValue();
if (value != null && value instanceof Element) {
Element idfElem = (Element) value;
if (itemId.denotesNode()) {
- definition = new QNodeDefinitionImpl(null, idfElem, getNamespaceResolver());
+ definition = new QNodeDefinitionImpl(null, idfElem, nsResolver);
} else {
- definition = new QPropertyDefinitionImpl(null, idfElem, getNamespaceResolver());
+ definition = new QPropertyDefinitionImpl(null, idfElem, nsResolver);
}
}
}
@@ -636,7 +646,7 @@
NodeId parentId = getParentId(propSet, sessionInfo);
NodeId id = uriResolver.buildNodeId(parentId, nodeResponse, sessionInfo.getWorkspaceName());
- NodeInfoImpl nInfo = new NodeInfoImpl(id, parentId, propSet, getNamespaceResolver());
+ NodeInfoImpl nInfo = new NodeInfoImpl(id, parentId, propSet, nsResolver);
for (Iterator it = childResponses.iterator(); it.hasNext();) {
MultiStatusResponse resp = (MultiStatusResponse) it.next();
@@ -657,7 +667,7 @@
Iterator hrefIter = refProp.getHrefs().iterator();
while(hrefIter.hasNext()) {
String propertyHref = hrefIter.next().toString();
- PropertyId propertyId = getURIResolver().getPropertyId(propertyHref, sessionInfo);
+ PropertyId propertyId = uriResolver.getPropertyId(propertyHref, sessionInfo);
nInfo.addReference(propertyId);
}
}
@@ -669,7 +679,7 @@
throw ExceptionConverter.generate(e);
} finally {
if (method != null) {
- //method.releaseConnection();
+ method.releaseConnection();
}
}
}
@@ -704,7 +714,7 @@
NodeId parentId = getParentId(propSet, sessionInfo);
PropertyId id = uriResolver.buildPropertyId(parentId, responses[0], sessionInfo.getWorkspaceName());
- PropertyInfo pInfo = new PropertyInfoImpl(id, parentId, propSet, getNamespaceResolver(), valueFactory);
+ PropertyInfo pInfo = new PropertyInfoImpl(id, parentId, propSet, nsResolver, valueFactory);
return pInfo;
} catch (IOException e) {
throw new RepositoryException(e);
@@ -718,14 +728,10 @@
}
/**
- * @see RepositoryService#createBatch(SessionInfo)
+ * @see RepositoryService#createBatch(ItemId, SessionInfo)
*/
- public Batch createBatch(SessionInfo sessionInfo) throws RepositoryException {
- if (sessionInfo instanceof SessionInfoImpl) {
- return new BatchImpl((SessionInfoImpl)sessionInfo);
- } else {
- throw new RepositoryException("Unknown SessionInfo implementation.");
- }
+ public Batch createBatch(ItemId itemId, SessionInfo sessionInfo) throws RepositoryException {
+ return new BatchImpl(itemId, sessionInfo);
}
/**
@@ -738,31 +744,33 @@
BatchImpl batchImpl = (BatchImpl) batch;
if (batchImpl.isEmpty()) {
batchImpl.dispose();
- // TODO build empty eventIterator
- return null;
+ return IteratorHelper.EMPTY;
}
// send batched information
try {
HttpClient client = batchImpl.start();
+ EventIterator events;
boolean success = false;
try {
Iterator it = batchImpl.methods();
while (it.hasNext()) {
DavMethod method = (DavMethod) it.next();
initMethod(method, batchImpl.sessionInfo, true);
+ // add batchId as separate header
+ CodedUrlHeader ch = new CodedUrlHeader(TransactionConstants.HEADER_TRANSACTIONID, batchImpl.batchId);
+ method.setRequestHeader(ch.getHeaderName(), ch.getHeaderValue());
client.executeMethod(method);
- if (!(success = method.succeeded())) {
- throw method.getResponseException();
- }
+ method.checkSuccess();
}
+ success = true;
} finally {
// make sure the lock is removed. if any of the methods
// failed the unlock is used to abort any pending changes
// on the server.
- batchImpl.end(client, success);
+ events = batchImpl.end(client, success);
}
- return retrieveEvents();
+ return events;
} catch (IOException e) {
throw new RepositoryException(e);
} catch (DavException e) {
@@ -776,80 +784,33 @@
* @see RepositoryService#importXml(SessionInfo, NodeId, InputStream, int)
*/
public EventIterator importXml(SessionInfo sessionInfo, NodeId parentId, InputStream xmlStream, int uuidBehaviour) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
- MkColMethod method = null;
- try {
- // TODO: improve. currently random name is built instead of retrieving name of new resource from top-level xml element within stream
- QName nodeName = new QName(QName.NS_DEFAULT_URI, UUID.randomUUID().toString());
- String uri = getItemUri(parentId, nodeName, sessionInfo);
- method = new MkColMethod(uri);
- initMethod(method, sessionInfo, true);
- method.setRequestEntity(new InputStreamRequestEntity(xmlStream, "text/xml"));
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
+ // TODO: improve. currently random name is built instead of retrieving name of new resource from top-level xml element within stream
+ QName nodeName = new QName(QName.NS_DEFAULT_URI, UUID.randomUUID().toString());
+ String uri = getItemUri(parentId, nodeName, sessionInfo);
+ MkColMethod method = new MkColMethod(uri);
+ method.setRequestEntity(new InputStreamRequestEntity(xmlStream, "text/xml"));
- return retrieveEvents();
- } catch (IOException e) {
- throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
- }
+ return execute(method, sessionInfo);
}
/**
* @see RepositoryService#move(SessionInfo, NodeId, NodeId, QName)
*/
public EventIterator move(SessionInfo sessionInfo, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
- MoveMethod method = null;
- try {
- String uri = getItemUri(srcNodeId, sessionInfo);
- String destUri = getItemUri(destParentNodeId, destName, sessionInfo);
- method = new MoveMethod(uri, destUri, true);
- initMethod(method, sessionInfo, true);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
-
- return retrieveEvents();
- } catch (IOException e) {
- throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
- }
+ String uri = getItemUri(srcNodeId, sessionInfo);
+ String destUri = getItemUri(destParentNodeId, destName, sessionInfo);
+ MoveMethod method = new MoveMethod(uri, destUri, true);
+ return execute(method, sessionInfo);
}
/**
* @see RepositoryService#copy(SessionInfo, String, NodeId, NodeId, QName)
*/
public EventIterator copy(SessionInfo sessionInfo, String srcWorkspaceName, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, UnsupportedRepositoryOperationException, RepositoryException {
- CopyMethod method = null;
- try {
- String uri = getItemUri(srcNodeId, srcWorkspaceName, sessionInfo);
- String destUri = getItemUri(destParentNodeId, destName, sessionInfo);
- method = new CopyMethod(uri, destUri, true, false);
- initMethod(method, sessionInfo, true);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
-
- return retrieveEvents();
- } catch (IOException e) {
- throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
- }
+ String uri = uriResolver.getItemUri(srcNodeId, srcWorkspaceName, sessionInfo);
+ String destUri = getItemUri(destParentNodeId, destName, sessionInfo);
+ CopyMethod method = new CopyMethod(uri, destUri, true, false);
+ return execute(method, sessionInfo);
}
/**
@@ -857,7 +818,7 @@
*/
public EventIterator update(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName) throws NoSuchWorkspaceException, AccessDeniedException, LockException, InvalidItemStateException, RepositoryException {
String uri = getItemUri(nodeId, sessionInfo);
- String workspUri = getWorkspaceUri(srcWorkspaceName);
+ String workspUri = uriResolver.getWorkspaceUri(srcWorkspaceName);
return update(uri, new String[] {workspUri}, UpdateInfo.UPDATE_BY_WORKSPACE, false, sessionInfo);
}
@@ -867,7 +828,7 @@
*/
public EventIterator clone(SessionInfo sessionInfo, String srcWorkspaceName, NodeId srcNodeId, NodeId destParentNodeId, QName destName, boolean removeExisting) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, UnsupportedRepositoryOperationException, RepositoryException {
// TODO: missing implementation
- return null;
+ throw new UnsupportedOperationException("Missing implementation");
}
/**
@@ -913,30 +874,20 @@
* @see RepositoryService#lock(SessionInfo, NodeId, boolean)
*/
public EventIterator lock(SessionInfo sessionInfo, NodeId nodeId, boolean deep) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException {
- LockMethod method = null;
try {
String uri = getItemUri(nodeId, sessionInfo);
- method = new LockMethod(uri, Scope.EXCLUSIVE, Type.WRITE, null, DavConstants.INFINITE_TIMEOUT, true);
- initMethod(method, sessionInfo, false);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
+ LockMethod method = new LockMethod(uri, Scope.EXCLUSIVE, Type.WRITE, null, DavConstants.INFINITE_TIMEOUT, true);
+ EventIterator events = execute(method, sessionInfo);
String lockToken = method.getLockToken();
sessionInfo.addLockToken(lockToken);
// TODO: ev. need to take care of 'timeout' ?
// TODO: ev. evaluate lock response, if depth and type is according to request?
+ return events;
- return retrieveEvents();
} catch (IOException e) {
throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
}
}
@@ -944,112 +895,51 @@
* @see RepositoryService#refreshLock(SessionInfo, NodeId)
*/
public EventIterator refreshLock(SessionInfo sessionInfo, NodeId nodeId) throws LockException, RepositoryException {
- LockMethod method = null;
- try {
- String uri = getItemUri(nodeId, sessionInfo);
- // since sessionInfo does not allow to retrieve token by NodeId,
- // pass all available lock tokens to the LOCK method (TODO: correct?)
- method = new LockMethod(uri, DavConstants.INFINITE_TIMEOUT, sessionInfo.getLockTokens());
- initMethod(method, sessionInfo, false);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
-
- return retrieveEvents();
- } catch (IOException e) {
- throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
- }
+ String uri = getItemUri(nodeId, sessionInfo);
+ // since sessionInfo does not allow to retrieve token by NodeId,
+ // pass all available lock tokens to the LOCK method (TODO: correct?)
+ LockMethod method = new LockMethod(uri, DavConstants.INFINITE_TIMEOUT, sessionInfo.getLockTokens());
+ return execute(method, sessionInfo);
}
/**
* @see RepositoryService#unlock(SessionInfo, NodeId)
*/
public EventIterator unlock(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException {
- UnLockMethod method = null;
- try {
- String uri = getItemUri(nodeId, sessionInfo);
- // Note: since sessionInfo does not allow to identify the id of the
- // lock holding node, we need to access the token via lockInfo
- // TODO: review this.
- LockInfo lInfo = getLockInfo(sessionInfo, nodeId);
- String lockToken = lInfo.getLockToken();
-
- // TODO: ev. additional check if lt is present on the sessionInfo?
+ String uri = getItemUri(nodeId, sessionInfo);
+ // Note: since sessionInfo does not allow to identify the id of the
+ // lock holding node, we need to access the token via lockInfo
+ // TODO: review this.
+ LockInfo lInfo = getLockInfo(sessionInfo, nodeId);
+ String lockToken = lInfo.getLockToken();
- method = new UnLockMethod(uri, lockToken);
- initMethod(method, sessionInfo, false);
+ // TODO: ev. additional check if lt is present on the sessionInfo?
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
+ UnLockMethod method = new UnLockMethod(uri, lockToken);
+ EventIterator events = execute(method, sessionInfo);
- sessionInfo.removeLockToken(lockToken);
-
- return retrieveEvents();
- } catch (IOException e) {
- throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
- }
+ sessionInfo.removeLockToken(lockToken);
+ return events;
}
/**
* @see RepositoryService#checkin(SessionInfo, NodeId)
*/
public EventIterator checkin(SessionInfo sessionInfo, NodeId nodeId) throws VersionException, UnsupportedRepositoryOperationException, InvalidItemStateException, LockException, RepositoryException {
- CheckinMethod method = null;
- try {
- String uri = getItemUri(nodeId, sessionInfo);
- method = new CheckinMethod(uri);
- initMethod(method, sessionInfo, true);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
+ String uri = getItemUri(nodeId, sessionInfo);
+ CheckinMethod method = new CheckinMethod(uri);
- return retrieveEvents();
- } catch (IOException e) {
- throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
- }
+ return execute(method, sessionInfo);
}
/**
* @see RepositoryService#checkout(SessionInfo, NodeId)
*/
public EventIterator checkout(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, RepositoryException {
- CheckoutMethod method = null;
- try {
- String uri = getItemUri(nodeId, sessionInfo);
- method = new CheckoutMethod(uri);
- initMethod(method, sessionInfo, true);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
+ String uri = getItemUri(nodeId, sessionInfo);
+ CheckoutMethod method = new CheckoutMethod(uri);
- return retrieveEvents();
- } catch (IOException e) {
- throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
- }
+ return execute(method, sessionInfo);
}
/**
@@ -1066,7 +956,7 @@
* @see RepositoryService#restore(SessionInfo, NodeId[], boolean)
*/
public EventIterator restore(SessionInfo sessionInfo, NodeId[] versionIds, boolean removeExisting) throws ItemExistsException, UnsupportedRepositoryOperationException, VersionException, LockException, InvalidItemStateException, RepositoryException {
- String uri = getWorkspaceUri(sessionInfo.getWorkspaceName());
+ String uri = uriResolver.getWorkspaceUri(sessionInfo.getWorkspaceName());
String[] vUris = new String[versionIds.length];
for (int i = 0; i < versionIds.length; i++) {
vUris[i] = getItemUri(versionIds[i], sessionInfo);
@@ -1076,7 +966,6 @@
}
private EventIterator update(String uri, String[] updateSource, int updateType, boolean removeExisting, SessionInfo sessionInfo) throws RepositoryException {
- UpdateMethod method = null;
try {
UpdateInfo uInfo;
if (removeExisting) {
@@ -1087,49 +976,30 @@
uInfo = new UpdateInfo(updateSource, updateType, new DavPropertyNameSet());
}
- method = new UpdateMethod(uri, uInfo);
- initMethod(method, sessionInfo, true);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
-
- return retrieveEvents();
+ UpdateMethod method = new UpdateMethod(uri, uInfo);
+ return execute(method, sessionInfo);
} catch (IOException e) {
throw new RepositoryException(e);
} catch (DavException e) {
throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
}
}
/**
* @see RepositoryService#merge(SessionInfo, NodeId, String, boolean)
*/
public EventIterator merge(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName, boolean bestEffort) throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException {
- MergeMethod method = null;
try {
- String wspHref = getWorkspaceUri(srcWorkspaceName);
+ String wspHref = uriResolver.getWorkspaceUri(srcWorkspaceName);
Element mElem = MergeInfo.createMergeElement(new String[] {wspHref}, bestEffort, false, domFactory);
MergeInfo mInfo = new MergeInfo(mElem);
- method = new MergeMethod(getItemUri(nodeId, sessionInfo), mInfo);
- initMethod(method, sessionInfo, true);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
-
+ MergeMethod method = new MergeMethod(getItemUri(nodeId, sessionInfo), mInfo);
// TODO: need to evaluate response?
- return retrieveEvents();
+ return execute(method, sessionInfo);
} catch (IOException e) {
throw new RepositoryException(e);
} catch (DavException e) {
throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
}
}
@@ -1137,7 +1007,6 @@
* @see RepositoryService#resolveMergeConflict(SessionInfo, NodeId, NodeId[], NodeId[])
*/
public EventIterator resolveMergeConflict(SessionInfo sessionInfo, NodeId nodeId, NodeId[] mergeFailedIds, NodeId[] predecessorIds) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException {
- PropPatchMethod method = null;
try {
List changeList = new ArrayList();
String[] mergeFailedHref = new String[mergeFailedIds.length];
@@ -1154,22 +1023,11 @@
changeList.add(new HrefProperty(VersionControlledResource.PREDECESSOR_SET, pdcHrefs, false));
}
- method = new PropPatchMethod(getItemUri(nodeId, sessionInfo), changeList);
- initMethod(method, sessionInfo, true);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
-
+ PropPatchMethod method = new PropPatchMethod(getItemUri(nodeId, sessionInfo), changeList);
// TODO: ev. evaluate response
- return retrieveEvents();
+ return execute(method, sessionInfo);
} catch (IOException e) {
throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
}
}
@@ -1177,26 +1035,14 @@
* @see RepositoryService#addVersionLabel(SessionInfo,NodeId,NodeId,QName,boolean)
*/
public EventIterator addVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label, boolean moveLabel) throws VersionException, RepositoryException {
- LabelMethod method = null;
- try {
+ try {
String uri = getItemUri(versionId, sessionInfo);
- method = new LabelMethod(uri, NameFormat.format(label, getNamespaceResolver()), (moveLabel) ? LabelInfo.TYPE_SET : LabelInfo.TYPE_ADD);
- initMethod(method, sessionInfo, true);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
-
- return retrieveEvents();
+ LabelMethod method = new LabelMethod(uri, NameFormat.format(label, nsResolver), (moveLabel) ? LabelInfo.TYPE_SET : LabelInfo.TYPE_ADD);
+ return execute(method, sessionInfo);
} catch (IOException e) {
throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
} catch (NoPrefixDeclaredException e) {
throw new RepositoryException(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
}
}
@@ -1204,26 +1050,14 @@
* @see RepositoryService#removeVersionLabel(SessionInfo,NodeId,NodeId,QName)
*/
public EventIterator removeVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label) throws VersionException, RepositoryException {
- LabelMethod method = null;
try {
String uri = getItemUri(versionId, sessionInfo);
- method = new LabelMethod(uri, NameFormat.format(label, getNamespaceResolver()), LabelInfo.TYPE_REMOVE);
- initMethod(method, sessionInfo, true);
-
- getClient(sessionInfo).executeMethod(method);
- method.checkSuccess();
-
- return retrieveEvents();
+ LabelMethod method = new LabelMethod(uri, NameFormat.format(label, nsResolver), LabelInfo.TYPE_REMOVE);
+ return execute(method, sessionInfo);
} catch (IOException e) {
throw new RepositoryException(e);
- } catch (DavException e) {
- throw ExceptionConverter.generate(e);
} catch (NoPrefixDeclaredException e) {
throw new RepositoryException(e);
- } finally {
- if (method != null) {
- method.releaseConnection();
- }
}
}
@@ -1231,7 +1065,7 @@
* @see RepositoryService#getSupportedQueryLanguages(SessionInfo)
*/
public String[] getSupportedQueryLanguages(SessionInfo sessionInfo) throws RepositoryException {
- OptionsMethod method = new OptionsMethod(getWorkspaceUri(sessionInfo.getWorkspaceName()));
+ OptionsMethod method = new OptionsMethod(uriResolver.getWorkspaceUri(sessionInfo.getWorkspaceName()));
try {
getClient(sessionInfo).executeMethod(method);
method.checkSuccess();
@@ -1243,6 +1077,10 @@
throw new RepositoryException(e);
} catch (DavException e) {
throw ExceptionConverter.generate(e);
+ } finally {
+ if (method != null) {
+ method.releaseConnection();
+ }
}
}
@@ -1250,23 +1088,29 @@
* @see RepositoryService#executeQuery(SessionInfo, String, String)
*/
public QueryInfo executeQuery(SessionInfo sessionInfo, String statement, String language) throws RepositoryException {
+ SearchMethod method = null;
try {
- SearchMethod method = new SearchMethod(getWorkspaceUri(sessionInfo.getWorkspaceName()), statement, language);
+ String uri = uriResolver.getWorkspaceUri(sessionInfo.getWorkspaceName());
+ method = new SearchMethod(uri, statement, language);
getClient(sessionInfo).executeMethod(method);
method.checkSuccess();
MultiStatus ms = method.getResponseBodyAsMultiStatus();
- return new QueryInfoImpl(ms, sessionInfo, getURIResolver(),
- getNamespaceResolver(), valueFactory);
+ return new QueryInfoImpl(ms, sessionInfo, uriResolver,
+ nsResolver, valueFactory);
} catch (IOException e) {
throw new RepositoryException(e);
} catch (DavException e) {
throw ExceptionConverter.generate(e);
+ } finally {
+ if (method != null) {
+ method.releaseConnection();
+ }
}
}
/**
- * @see RepositoryService#addEventListener(SessionInfo, NodeId, EventListener, int, boolean, String[], QName[])
+ * @see RepositoryService#addEventListener(SessionInfo,NodeId,EventListener,int,boolean,String[],QName[])
*/
public void addEventListener(SessionInfo sessionInfo, NodeId nodeId, EventListener listener, int eventTypes, boolean isDeep, String[] uuids, QName[] nodeTypeIds) throws RepositoryException {
// build event types
@@ -1290,31 +1134,116 @@
// build filters from params
List filters = new ArrayList();
- for (int i = 0; i < uuids.length; i++) {
+ for (int i = 0; uuids != null && i < uuids.length; i++) {
filters.add(new Filter(ObservationConstants.XML_UUID, ObservationConstants.NAMESPACE, uuids[i]));
}
- for (int i = 0; i < nodeTypeIds.length; i++) {
+ for (int i = 0; nodeTypeIds != null && i < nodeTypeIds.length; i++) {
try {
- String ntName = NameFormat.format(nodeTypeIds[i], getNamespaceResolver());
+ String ntName = NameFormat.format(nodeTypeIds[i], nsResolver);
filters.add(new Filter(ObservationConstants.XML_NODETYPE_NAME, ObservationConstants.NAMESPACE, ntName));
} catch (NoPrefixDeclaredException e) {
throw new RepositoryException(e);
}
}
Filter[] ftArr = (Filter[]) filters.toArray(new Filter[filters.size()]);
- // always 'noLocal' since local changes are reported by return values
- boolean noLocal = true;
+ boolean noLocal = true;
SubscriptionInfo subscriptionInfo = new SubscriptionInfo(etArr, ftArr, noLocal, isDeep, DavConstants.UNDEFINED_TIMEOUT);
+ String uri = getItemUri(nodeId, sessionInfo);
- // TODO: missing implementation
+ checkSessionInfo(sessionInfo);
+ SubscriptionManager sMgr = ((SessionInfoImpl)sessionInfo).getSubscriptionManager();
+
+ if (sMgr.subscriptionExists(listener)) {
+ String subscriptionId = sMgr.getSubscriptionId(listener);
+ subscribe(uri, subscriptionInfo, subscriptionId, sessionInfo);
+ log.debug("Subscribed on server for listener " + listener);
+ } else {
+ String subscriptionId = subscribe(uri, subscriptionInfo, null, sessionInfo);
+ log.debug("Subscribed on server for listener " + listener);
+ sMgr.addSubscription(uri, subscriptionId, listener);
+ log.debug("Added subscription for listener " + listener);
+ }
}
/**
* @see RepositoryService#removeEventListener(SessionInfo, NodeId, EventListener)
*/
public void removeEventListener(SessionInfo sessionInfo, NodeId nodeId, EventListener listener) throws RepositoryException {
- // TODO: missing implementation
+ checkSessionInfo(sessionInfo);
+ SubscriptionManager sMgr = ((SessionInfoImpl)sessionInfo).getSubscriptionManager();
+ String subscriptionId = sMgr.getSubscriptionId(listener);
+
+ String uri = getItemUri(nodeId, sessionInfo);
+ sMgr.removeSubscription(listener);
+ log.debug("Removed subscription for listener " + listener);
+ unsubscribe(uri, subscriptionId, sessionInfo);
+ log.debug("Unsubscribed on server for listener " + listener);
+ }
+
+
+ private String subscribe(String uri, SubscriptionInfo subscriptionInfo, String subscriptionId, SessionInfo sessionInfo) throws RepositoryException {
+ SubscribeMethod method = null;
+ try {
+ if (subscriptionId != null) {
+ method = new SubscribeMethod(uri, subscriptionInfo, subscriptionId);
+ } else {
+ method = new SubscribeMethod(uri, subscriptionInfo);
+ }
+ getClient(sessionInfo).executeMethod(method);
+ method.checkSuccess();
+ return method.getSubscriptionId();
+ } catch (IOException e) {
+ throw new RepositoryException(e);
+ } catch (DavException e) {
+ throw ExceptionConverter.generate(e);
+ } finally {
+ if (method != null) {
+ method.releaseConnection();
+ }
+ }
+ }
+
+ private void unsubscribe(String uri, String subscriptionId, SessionInfo sessionInfo) throws RepositoryException {
+ UnSubscribeMethod method = null;
+ try {
+ method = new UnSubscribeMethod(uri, subscriptionId);
+ getClient(sessionInfo).executeMethod(method);
+ method.checkSuccess();
+ } catch (IOException e) {
+ throw new RepositoryException(e);
+ } catch (DavException e) {
+ throw ExceptionConverter.generate(e);
+ } finally {
+ if (method != null) {
+ method.releaseConnection();
+ }
+ }
+ }
+
+ private EventIterator poll(String uri, String subscriptionId, SessionInfo sessionInfo) throws RepositoryException {
+ PollMethod method = null;
+ try {
+ method = new PollMethod(uri, subscriptionId);
+ getClient(sessionInfo).executeMethod(method);
+ method.checkSuccess();
+
+ EventDiscovery disc = method.getResponseAsEventDiscovery();
+ if (disc.isEmpty()) {
+ return IteratorHelper.EMPTY;
+ } else {
+ Element discEl = disc.toXml(domFactory);
+ return new EventIteratorImpl(discEl, uriResolver, sessionInfo);
+ }
+ } catch (IOException e) {
+ throw new RepositoryException(e);
+ } catch (DavException e) {
+ throw ExceptionConverter.generate(e);
+ } finally {
+ if (method != null) {
+ method.releaseConnection();
+ }
+ }
}
/**
@@ -1324,7 +1253,7 @@
ReportInfo info = new ReportInfo(RegisteredNamespacesReport.REGISTERED_NAMESPACES_REPORT, DEPTH_0);
ReportMethod method = null;
try {
- method = new ReportMethod(getWorkspaceUri(sessionInfo.getWorkspaceName()), info);
+ method = new ReportMethod(uriResolver.getWorkspaceUri(sessionInfo.getWorkspaceName()), info);
getClient(sessionInfo).executeMethod(method);
method.checkSuccess();
@@ -1407,7 +1336,7 @@
PropPatchMethod method = null;
try {
- String uri = getWorkspaceUri(sessionInfo.getWorkspaceName());
+ String uri = uriResolver.getWorkspaceUri(sessionInfo.getWorkspaceName());
method = new PropPatchMethod(uri, setProperties, new DavPropertyNameSet());
initMethod(method, sessionInfo, true);
@@ -1434,7 +1363,8 @@
ReportMethod method = null;
try {
- method = new ReportMethod(getWorkspaceUri(sessionInfo.getWorkspaceName()), info);
+ String workspaceUri = uriResolver.getWorkspaceUri(sessionInfo.getWorkspaceName());
+ method = new ReportMethod(workspaceUri, info);
getClient(sessionInfo).executeMethod(method);
method.checkSuccess();
@@ -1442,7 +1372,7 @@
ElementIterator it = DomUtil.getChildren(reportDoc.getDocumentElement(), NodeTypeConstants.NODETYPE_ELEMENT, null);
List ntDefs = new ArrayList();
while (it.hasNext()) {
- ntDefs.add(new QNodeTypeDefinitionImpl(it.nextElement(), getNamespaceResolver()));
+ ntDefs.add(new QNodeTypeDefinitionImpl(it.nextElement(), nsResolver));
}
return new IteratorHelper(ntDefs);
} catch (IOException e) {
@@ -1480,22 +1410,38 @@
throw new UnsupportedRepositoryOperationException("JSR170 does not defined methods to unregister nodetypes.");
}
+ /**
+ * The XML elements and attributes used in serialization
+ */
+ private static final Namespace SV_NAMESPACE = Namespace.getNamespace(QName.NS_SV_PREFIX, QName.NS_SV_URI);
+ private static final String NODE_ELEMENT = "node";
+ private static final String PROPERTY_ELEMENT = "property";
+ private static final String VALUE_ELEMENT = "value";
+ private static final String NAME_ATTRIBUTE = "name";
+ private static final String TYPE_ATTRIBUTE = "type";
+
//------------------------------------------------< Inner Class 'Batch' >---
private class BatchImpl implements Batch {
- private final SessionInfoImpl sessionInfo;
+ private final SessionInfo sessionInfo;
+ private final ItemId targetId;
private final List methods = new ArrayList();
+ private String batchId;
+ private String subscriptionId;
+
private boolean isConsumed = false;
- private BatchImpl(SessionInfoImpl sessionInfo) {
+ private BatchImpl(ItemId targetId, SessionInfo sessionInfo) {
+ this.targetId = targetId;
this.sessionInfo = sessionInfo;
}
private HttpClient start() throws RepositoryException {
checkConsumed();
try {
- String uri = getRootItemUri(sessionInfo.getWorkspaceName());
+ String uri = getItemUri(targetId, sessionInfo);
+ // start special 'lock'
LockMethod method = new LockMethod(uri, TransactionConstants.LOCAL, TransactionConstants.TRANSACTION, null, DavConstants.INFINITE_TIMEOUT, true);
initMethod(method, sessionInfo, false);
@@ -1503,8 +1449,11 @@
client.executeMethod(method);
method.checkSuccess();
- String batchId = method.getLockToken();
- sessionInfo.setBatchId(batchId);
+ batchId = method.getLockToken();
+
+ // register subscription
+ String subscrUri = (targetId.denotesNode() ? uri : getItemUri(((PropertyId) targetId).getParentId(), sessionInfo));
+ subscriptionId = subscribe(subscrUri, S_INFO, null, sessionInfo);
return client;
} catch (IOException e) {
throw new RepositoryException(e);
@@ -1513,11 +1462,11 @@
}
}
- private void end(HttpClient client, boolean discard) throws RepositoryException {
+ private EventIterator end(HttpClient client, boolean commit) throws RepositoryException {
checkConsumed();
try {
- String uri = getRootItemUri(sessionInfo.getWorkspaceName());
- UnLockMethod method = new UnLockMethod(uri, sessionInfo.getBatchId());
+ String uri = getItemUri(targetId, sessionInfo);
+ UnLockMethod method = new UnLockMethod(uri, batchId);
// todo: check if 'initmethod' would work (ev. conflict with TxId header).
String[] locktokens = sessionInfo.getLockTokens();
if (locktokens != null && locktokens.length > 0) {
@@ -1526,12 +1475,17 @@
}
// in contrast to standard UNLOCK, the tx-unlock provides a
// request body.
- method.setRequestBody(new TransactionInfo(!discard));
+ method.setRequestBody(new TransactionInfo(commit));
client.executeMethod(method);
method.checkSuccess();
- // make sure the batchId on the sessionInfo is reset.
- sessionInfo.setBatchId(null);
+
+ // retrieve events && unsubscribe
+ String subscrUri = (targetId.denotesNode() ? uri : getItemUri(((PropertyId) targetId).getParentId(), sessionInfo));
+ EventIterator events = poll(subscrUri, subscriptionId, sessionInfo);
+ unsubscribe(subscrUri, subscriptionId, sessionInfo);
+
+ return events;
} catch (IOException e) {
throw new RepositoryException(e);
} catch (DavException e) {
@@ -1560,16 +1514,6 @@
//----------------------------------------------------------< Batch >---
/**
- * The XML elements and attributes used in serialization
- */
- private final Namespace SV_NAMESPACE = Namespace.getNamespace(QName.NS_SV_PREFIX, QName.NS_SV_URI);
- private final String NODE_ELEMENT = "node";
- private final String PROPERTY_ELEMENT = "property";
- private final String VALUE_ELEMENT = "value";
- private final String NAME_ATTRIBUTE = "name";
- private final String TYPE_ATTRIBUTE = "type";
-
- /**
* @see Batch#addNode(NodeId, QName, QName, String)
*/
public void addNode(NodeId parentId, QName nodeName, QName nodetypeName, String uuid) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, NoSuchNodeTypeException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
@@ -1586,13 +1530,13 @@
if (nodetypeName != null) {
Element propElement = DomUtil.addChildElement(nodeElement, PROPERTY_ELEMENT, SV_NAMESPACE);
- DomUtil.setAttribute(propElement, NAME_ATTRIBUTE, SV_NAMESPACE, NameFormat.format(QName.JCR_PRIMARYTYPE, getNamespaceResolver()));
+ DomUtil.setAttribute(propElement, NAME_ATTRIBUTE, SV_NAMESPACE, NameFormat.format(QName.JCR_PRIMARYTYPE, nsResolver));
DomUtil.setAttribute(propElement, TYPE_ATTRIBUTE, SV_NAMESPACE, PropertyType.nameFromValue(PropertyType.NAME));
- DomUtil.addChildElement(propElement, VALUE_ELEMENT, SV_NAMESPACE, NameFormat.format(nodetypeName, getNamespaceResolver()));
+ DomUtil.addChildElement(propElement, VALUE_ELEMENT, SV_NAMESPACE, NameFormat.format(nodetypeName, nsResolver));
}
if (uuid != null) {
Element propElement = DomUtil.addChildElement(nodeElement, PROPERTY_ELEMENT, SV_NAMESPACE);
- DomUtil.setAttribute(propElement, NAME_ATTRIBUTE, SV_NAMESPACE, NameFormat.format(QName.JCR_UUID, getNamespaceResolver()));
+ DomUtil.setAttribute(propElement, NAME_ATTRIBUTE, SV_NAMESPACE, NameFormat.format(QName.JCR_UUID, nsResolver));
DomUtil.setAttribute(propElement, TYPE_ATTRIBUTE, SV_NAMESPACE, PropertyType.nameFromValue(PropertyType.STRING));
DomUtil.addChildElement(propElement, VALUE_ELEMENT, SV_NAMESPACE, uuid);
}
@@ -1615,7 +1559,7 @@
public void addProperty(NodeId parentId, QName propertyName, String value, int propertyType) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, PathNotFoundException, ItemExistsException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
checkConsumed();
QValue qV = QValue.create(value, propertyType);
- Value jcrValue = ValueFormat.getJCRValue(qV, getNamespaceResolver(), valueFactory);
+ Value jcrValue = ValueFormat.getJCRValue(qV, nsResolver, valueFactory);
ValuesProperty vp = new ValuesProperty(jcrValue);
internalAddProperty(parentId, propertyName, vp);
}
@@ -1628,7 +1572,7 @@
Value[] jcrValues = new Value[values.length];
for (int i = 0; i < values.length; i++) {
QValue v = QValue.create(values[i], propertyType);
- jcrValues[i] = ValueFormat.getJCRValue(v, getNamespaceResolver(), valueFactory);
+ jcrValues[i] = ValueFormat.getJCRValue(v, nsResolver, valueFactory);
}
ValuesProperty vp = new ValuesProperty(jcrValues);
internalAddProperty(parentId, propertyName, vp);
@@ -1642,7 +1586,7 @@
QValue qV = null;
try {
qV = QValue.create(value, propertyType);
- Value jcrValue = ValueFormat.getJCRValue(qV, getNamespaceResolver(), valueFactory);
+ Value jcrValue = ValueFormat.getJCRValue(qV, nsResolver, valueFactory);
ValuesProperty vp = new ValuesProperty(jcrValue);
internalAddProperty(parentId, propertyName, vp);
} catch (IOException e) {
@@ -1659,7 +1603,7 @@
Value[] jcrValues = new Value[values.length];
for (int i = 0; i < values.length; i++) {
QValue qV = QValue.create(values[i], propertyType);
- jcrValues[i] = ValueFormat.getJCRValue(qV, getNamespaceResolver(), valueFactory);
+ jcrValues[i] = ValueFormat.getJCRValue(qV, nsResolver, valueFactory);
}
ValuesProperty vp = new ValuesProperty(jcrValues);
internalAddProperty(parentId, propertyName, vp);
@@ -1693,7 +1637,7 @@
} else {
// qualified value must be converted to jcr value
QValue qV = QValue.create(value, propertyType);
- Value jcrValue = ValueFormat.getJCRValue(qV, getNamespaceResolver(), valueFactory);
+ Value jcrValue = ValueFormat.getJCRValue(qV, nsResolver, valueFactory);
ValuesProperty vp = new ValuesProperty(jcrValue);
setProperties.add(vp);
}
@@ -1714,7 +1658,7 @@
Value[] jcrValues = new Value[values.length];
for (int i = 0; i < values.length; i++) {
QValue qV = QValue.create(values[i], propertyType);
- jcrValues[i] = ValueFormat.getJCRValue(qV, getNamespaceResolver(), valueFactory);
+ jcrValues[i] = ValueFormat.getJCRValue(qV, nsResolver, valueFactory);
}
setProperties.add(new ValuesProperty(jcrValues));
}
@@ -1734,7 +1678,7 @@
} else {
// qualified value must be converted to jcr value
QValue qV = QValue.create(value, propertyType);
- Value jcrValue = ValueFormat.getJCRValue(qV, getNamespaceResolver(), valueFactory);
+ Value jcrValue = ValueFormat.getJCRValue(qV, nsResolver, valueFactory);
ValuesProperty vp = new ValuesProperty(jcrValue);
setProperties.add(vp);
}
@@ -1759,7 +1703,7 @@
Value[] jcrValues = new Value[values.length];
for (int i = 0; i < values.length; i++) {
QValue qV = QValue.create(values[i], propertyType);
- jcrValues[i] = ValueFormat.getJCRValue(qV, getNamespaceResolver(), valueFactory);
+ jcrValues[i] = ValueFormat.getJCRValue(qV, nsResolver, valueFactory);
}
setProperties.add(new ValuesProperty(jcrValues));
}
@@ -1837,7 +1781,7 @@
} else {
String[] ntNames = new String[mixinNodeTypeIds.length];
for (int i = 0; i < mixinNodeTypeIds.length; i++) {
- ntNames[i] = NameFormat.format(mixinNodeTypeIds[i], getNamespaceResolver());
+ ntNames[i] = NameFormat.format(mixinNodeTypeIds[i], nsResolver);
}
setProperties = new DavPropertySet();
setProperties.add(new NodeTypeProperty(ItemResourceConstants.JCR_MIXINNODETYPES, ntNames, false));
@@ -1866,6 +1810,100 @@
MoveMethod method = new MoveMethod(uri, destUri, true);
methods.add(method);
+ }
+ }
+
+ /**
+ * <code>SubscriptionManager</code>...
+ */
+ private class SubscriptionMgrImpl implements SubscriptionManager {
+
+ private SessionInfo sessionInfo;
+
+ private final Map subscriptions = new HashMap();
+ private final Object subscriptionsLock = new Object();
+ private Map currentSubscriptions;
+
+ private Thread t;
+
+ public void setSessionInfo(SessionInfo sessionInfo) {
+ this.sessionInfo = sessionInfo;
+ }
+
+ public boolean subscriptionExists(EventListener listener) {
+ return getSubscriptions().containsKey(listener);
+ }
+
+ public String getSubscriptionId(EventListener listener) {
+ if (getSubscriptions().containsKey(listener)) {
+ return ((String[]) getSubscriptions().get(listener))[1];
+ } else {
+ return null;
+ }
+ }
+
+ public void addSubscription(String uri, String subscriptionId, EventListener listener) {
+ synchronized (subscriptionsLock) {
+ boolean doStart = subscriptions.isEmpty();
+ subscriptions.put(listener, new String[] {uri,subscriptionId});
+ currentSubscriptions = null;
+ if (doStart) {
+ startPolling();
+ }
+ }
+ }
+
+ public synchronized void removeSubscription(EventListener listener) {
+ synchronized (subscriptionsLock) {
+ subscriptions.remove(listener);
+ currentSubscriptions = null;
+ if (subscriptions.isEmpty()) {
+ stopPolling();
+ }
+ }
+ }
+
+ private Map getSubscriptions() {
+ synchronized (subscriptionsLock) {
+ if (currentSubscriptions == null) {
+ currentSubscriptions = Collections.unmodifiableMap(new HashMap(subscriptions));
+ }
+ return currentSubscriptions;
+ }
+ }
+
+ private void startPolling() {
+ Runnable r = new Runnable() {
+ public void run() {
+ while (t == Thread.currentThread()) {
+ try {
+ // sleep
+ Thread.sleep(POLL_INTERVAL);
+ // poll
+ Iterator lstnIterator = getSubscriptions().keySet().iterator();
+ while (lstnIterator.hasNext()) {
+ EventListener listener = (EventListener) lstnIterator.next();
+ String[] value = (String[]) getSubscriptions().get(listener);
+ String uri = value[0];
+ String subscriptionId = value[1];
+ EventIterator eventIterator = poll(uri, subscriptionId, sessionInfo);
+ listener.onEvent(eventIterator);
+ }
+ } catch (InterruptedException e) {
+ log.debug("Polling thread interrupted: " + e.getMessage());
+ return;
+ } catch (RepositoryException e) {
+ log.warn("Polling failed: ", e.getMessage());
+ }
+ }
+ }
+ };
+ t = new Thread(r);
+ t.start();
+ }
+
+ private void stopPolling() {
+ t.interrupt();
}
}
}
Modified: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SessionInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SessionInfoImpl.java?view=diff&rev=451313&r1=451312&r2=451313
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SessionInfoImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SessionInfoImpl.java Fri Sep 29 07:44:39 2006
@@ -20,8 +20,7 @@
import org.slf4j.Logger;
import org.apache.jackrabbit.spi.SessionInfo;
-import javax.jcr.Credentials;
-import javax.jcr.SimpleCredentials;
+
import java.util.HashSet;
import java.util.Set;
@@ -32,50 +31,61 @@
private static Logger log = LoggerFactory.getLogger(SessionInfoImpl.class);
- private final Credentials credentials;
+ private final CredentialsWrapper credentials;
private final String workspaceName;
- private String batchId;
+ private final SubscriptionManager subscrMgr;
private final Set lockTokens = new HashSet();
- SessionInfoImpl(Credentials creds, String workspaceName) {
+ SessionInfoImpl(CredentialsWrapper creds, String workspaceName, SubscriptionManager subscrMgr) {
this.credentials = creds;
this.workspaceName = workspaceName;
+ this.subscrMgr = subscrMgr;
+ subscrMgr.setSessionInfo(this);
}
+ //--------------------------------------------------------< SessionInfo >---
+ /**
+ * @inheritDoc
+ */
public String getUserID() {
- if (credentials instanceof SimpleCredentials) {
- return ((SimpleCredentials) credentials).getUserID();
- } else {
- return null;
- }
+ return credentials.getUserId();
}
+ /**
+ * @inheritDoc
+ */
public String getWorkspaceName() {
return workspaceName;
}
+ /**
+ * @inheritDoc
+ */
public String[] getLockTokens() {
return (String[]) lockTokens.toArray(new String[lockTokens.size()]);
}
+ /**
+ * @inheritDoc
+ */
public void addLockToken(String lockToken) {
lockTokens.add(lockToken);
}
+ /**
+ * @inheritDoc
+ */
public void removeLockToken(String lockToken) {
lockTokens.remove(lockToken);
}
- public String getBatchId() {
- return batchId;
- }
-
- public void setBatchId(String id) {
- batchId = id;
+ //--------------------------------------------------------------------------
+ CredentialsWrapper getCredentials() {
+ return credentials;
}
- Credentials getCredentials() {
- return credentials;
+ SubscriptionManager getSubscriptionManager() {
+ return subscrMgr;
}
}
Added: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SubscriptionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SubscriptionManager.java?view=auto&rev=451313
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SubscriptionManager.java (added)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SubscriptionManager.java Fri Sep 29 07:44:39 2006
@@ -0,0 +1,36 @@
+/*
+ * 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.spi2dav;
+
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.EventListener;
+
+/**
+ * <code>SubscriptionManager</code>...
+ */
+interface SubscriptionManager {
+
+ public void setSessionInfo(SessionInfo sessionInfo);
+
+ public boolean subscriptionExists(EventListener listener);
+
+ public String getSubscriptionId(EventListener listener);
+
+ public void addSubscription(String uri, String subscriptionId, EventListener listener);
+
+ public void removeSubscription(EventListener listener);
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SubscriptionManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SubscriptionManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java?view=diff&rev=451313&r1=451312&r2=451313
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java Fri Sep 29 07:44:39 2006
@@ -39,14 +39,11 @@
import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import org.apache.jackrabbit.webdav.client.methods.ReportMethod;
-import org.apache.jackrabbit.webdav.client.methods.DavMethod;
import org.apache.jackrabbit.webdav.MultiStatusResponse;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.DavServletResponse;
import org.apache.jackrabbit.webdav.DavConstants;
-import org.apache.jackrabbit.webdav.transaction.TransactionConstants;
-import org.apache.jackrabbit.webdav.header.CodedUrlHeader;
import org.apache.jackrabbit.webdav.xml.DomUtil;
import org.apache.jackrabbit.webdav.version.report.ReportInfo;
import org.apache.jackrabbit.BaseException;
@@ -83,16 +80,6 @@
this.domFactory = domFactory;
}
- private static void initMethod(DavMethod method, SessionInfo sessionInfo) {
- if (sessionInfo instanceof SessionInfoImpl) {
- String txId = ((SessionInfoImpl) sessionInfo).getBatchId();
- if (txId != null) {
- CodedUrlHeader ch = new CodedUrlHeader(TransactionConstants.HEADER_TRANSACTIONID, txId);
- method.setRequestHeader(ch.getHeaderName(), ch.getHeaderValue());
- }
- }
- }
-
private IdURICache getCache(String workspaceName) {
if (idURICaches.containsKey(workspaceName)) {
return (IdURICache) idURICaches.get(workspaceName);
@@ -144,7 +131,6 @@
try {
String wspUri = getWorkspaceUri(workspaceName);
ReportMethod rm = new ReportMethod(wspUri, rInfo);
- initMethod(rm, sessionInfo);
service.getClient(sessionInfo).executeMethod(rm);
@@ -307,7 +293,6 @@
DavMethodBase method = null;
try {
method = new PropFindMethod(uri, nameSet, DavConstants.DEPTH_0);
- initMethod(method, sessionInfo);
service.getClient(sessionInfo).executeMethod(method);
MultiStatusResponse[] responses = method.getResponseBodyAsMultiStatus().getResponses();