mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Remote AVM Store REST API now supports "list" and "listall" to retrieve lists and recursive lists of document paths.
Much improved JUnit test for RemoteStore - on web-tier end. - various issues fixed in existing API as highlighted by JUnit tests Separated out RemoteStore test from the RemoteClient JUnit test into own file. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@9530 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
<webscript>
|
<webscript>
|
||||||
<shortname>Remote AVM Store</shortname>
|
<shortname>Remote AVM Store</shortname>
|
||||||
<description>Remote service mirroring the Store interface - to an AVM store</description>
|
<description>Remote service mirroring the Store interface - to an AVM store</description>
|
||||||
|
<url>/remotestore/{method}</url>
|
||||||
<url>/remotestore/{method}/{path}</url>
|
<url>/remotestore/{method}/{path}</url>
|
||||||
<authentication>admin</authentication>
|
<authentication>admin</authentication>
|
||||||
<format default="">argument</format>
|
<format default="">argument</format>
|
||||||
|
@@ -28,11 +28,14 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
|
||||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
|
import org.alfresco.service.cmr.avm.AVMExistsException;
|
||||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||||
|
import org.alfresco.service.cmr.avm.AVMNotFoundException;
|
||||||
import org.alfresco.service.cmr.avm.AVMService;
|
import org.alfresco.service.cmr.avm.AVMService;
|
||||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
@@ -47,7 +50,7 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
/**
|
/**
|
||||||
* AVM Remote Store service.
|
* AVM Remote Store service.
|
||||||
*
|
*
|
||||||
* @see BaseRemoteStore for API methods.
|
* @see BaseRemoteStore for the available API methods.
|
||||||
*
|
*
|
||||||
* @author Kevin Roast
|
* @author Kevin Roast
|
||||||
*/
|
*/
|
||||||
@@ -107,7 +110,8 @@ public class AVMRemoteStore extends BaseRemoteStore
|
|||||||
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
||||||
if (desc == null)
|
if (desc == null)
|
||||||
{
|
{
|
||||||
throw new WebScriptException("Unable to locate file: " + avmPath);
|
res.setStatus(Status.STATUS_NOT_FOUND);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentReader reader;
|
ContentReader reader;
|
||||||
@@ -167,6 +171,10 @@ public class AVMRemoteStore extends BaseRemoteStore
|
|||||||
{
|
{
|
||||||
res.setStatus(Status.STATUS_UNAUTHORIZED);
|
res.setStatus(Status.STATUS_UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
|
catch (AVMNotFoundException avmErr)
|
||||||
|
{
|
||||||
|
res.setStatus(Status.STATUS_NOT_FOUND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
@@ -190,21 +198,33 @@ public class AVMRemoteStore extends BaseRemoteStore
|
|||||||
protected void createDocument(WebScriptResponse res, String path, InputStream content)
|
protected void createDocument(WebScriptResponse res, String path, InputStream content)
|
||||||
{
|
{
|
||||||
String avmPath = buildAVMPath(path);
|
String avmPath = buildAVMPath(path);
|
||||||
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
|
||||||
if (desc != null)
|
|
||||||
{
|
|
||||||
throw new WebScriptException("Unable to create, file already exists: " + avmPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] parts = AVMNodeConverter.SplitBase(avmPath);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
String[] parts = AVMNodeConverter.SplitBase(avmPath);
|
||||||
|
String[] dirs = parts[0].split("/");
|
||||||
|
String parentPath = dirs[0] + "/" + dirs[1];
|
||||||
|
int index = 2;
|
||||||
|
while (index < dirs.length)
|
||||||
|
{
|
||||||
|
String dirPath = parentPath + "/" + dirs[index];
|
||||||
|
if (this.avmService.lookup(-1, dirPath) == null)
|
||||||
|
{
|
||||||
|
this.avmService.createDirectory(parentPath, dirs[index]);
|
||||||
|
}
|
||||||
|
parentPath = dirPath;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
this.avmService.createFile(parts[0], parts[1], content);
|
this.avmService.createFile(parts[0], parts[1], content);
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException ae)
|
catch (AccessDeniedException ae)
|
||||||
{
|
{
|
||||||
res.setStatus(Status.STATUS_UNAUTHORIZED);
|
res.setStatus(Status.STATUS_UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
|
catch (AVMExistsException avmErr)
|
||||||
|
{
|
||||||
|
res.setStatus(Status.STATUS_CONFLICT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
@@ -217,7 +237,8 @@ public class AVMRemoteStore extends BaseRemoteStore
|
|||||||
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
||||||
if (desc == null)
|
if (desc == null)
|
||||||
{
|
{
|
||||||
throw new WebScriptException("Unable to locate file for update: " + avmPath);
|
res.setStatus(Status.STATUS_NOT_FOUND);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -231,6 +252,53 @@ public class AVMRemoteStore extends BaseRemoteStore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.web.scripts.bean.BaseRemoteStore#listDocuments(org.alfresco.web.scripts.WebScriptResponse, java.lang.String, boolean)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void listDocuments(WebScriptResponse res, String path, boolean recurse) throws IOException
|
||||||
|
{
|
||||||
|
String avmPath = buildAVMPath(path);
|
||||||
|
AVMNodeDescriptor node = this.avmService.lookup(-1, avmPath);
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
res.setStatus(Status.STATUS_NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
traverseNode(res.getWriter(), node, recurse);
|
||||||
|
}
|
||||||
|
catch (AccessDeniedException ae)
|
||||||
|
{
|
||||||
|
res.setStatus(Status.STATUS_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
res.getWriter().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void traverseNode(Writer out, AVMNodeDescriptor node, boolean recurse)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
int cropPoint = this.store.length() + this.rootPath.length() + 3;
|
||||||
|
SortedMap<String, AVMNodeDescriptor> listing = this.avmService.getDirectoryListing(node);
|
||||||
|
for (AVMNodeDescriptor n : listing.values())
|
||||||
|
{
|
||||||
|
if (n.isFile())
|
||||||
|
{
|
||||||
|
out.write(n.getPath().substring(cropPoint));
|
||||||
|
out.write("\n");
|
||||||
|
}
|
||||||
|
else if (recurse && n.isDirectory())
|
||||||
|
{
|
||||||
|
traverseNode(out, n, recurse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param path root path relative
|
* @param path root path relative
|
||||||
*
|
*
|
||||||
@@ -238,6 +306,6 @@ public class AVMRemoteStore extends BaseRemoteStore
|
|||||||
*/
|
*/
|
||||||
private String buildAVMPath(String path)
|
private String buildAVMPath(String path)
|
||||||
{
|
{
|
||||||
return this.store + ":/" + this.rootPath + "/" + path;
|
return this.store + ":/" + this.rootPath + (path != null ? ("/" + path) : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
|
||||||
import org.alfresco.web.scripts.AbstractWebScript;
|
import org.alfresco.web.scripts.AbstractWebScript;
|
||||||
import org.alfresco.web.scripts.WebScriptException;
|
import org.alfresco.web.scripts.WebScriptException;
|
||||||
import org.alfresco.web.scripts.WebScriptRequest;
|
import org.alfresco.web.scripts.WebScriptRequest;
|
||||||
@@ -69,6 +68,8 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
* GET has -> return true/false of existence for a document
|
* GET has -> return true/false of existence for a document
|
||||||
* GET get -> return document content - in addition the usual HTTP headers for the
|
* GET get -> return document content - in addition the usual HTTP headers for the
|
||||||
* character encoding, content type, length and modified date will be supplied
|
* character encoding, content type, length and modified date will be supplied
|
||||||
|
* GET list -> return the list of available document paths under a path
|
||||||
|
* GET listall -> return the list of available document paths (recursively) under a given path
|
||||||
* POST create -> create a new document with request content payload
|
* POST create -> create a new document with request content payload
|
||||||
* POST update -> update an existing document with request content payload
|
* POST update -> update an existing document with request content payload
|
||||||
*
|
*
|
||||||
@@ -127,13 +128,13 @@ public abstract class BaseRemoteStore extends AbstractWebScript
|
|||||||
{
|
{
|
||||||
throw new WebScriptException("Remote Store expecting method name.");
|
throw new WebScriptException("Remote Store expecting method name.");
|
||||||
}
|
}
|
||||||
if (extParts.length < 2)
|
|
||||||
{
|
|
||||||
throw new WebScriptException("Remote Store expecting document path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// build path as a string and as a list of path elements
|
// extract path from url extension
|
||||||
String path = req.getExtensionPath().substring(extParts[0].length() + 1);
|
String path = null;
|
||||||
|
if (extParts.length >= 2)
|
||||||
|
{
|
||||||
|
path = req.getExtensionPath().substring(extParts[0].length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug("Remote store method: " + extParts[0] + " path: " + path);
|
logger.debug("Remote store method: " + extParts[0] + " path: " + path);
|
||||||
@@ -147,22 +148,49 @@ public abstract class BaseRemoteStore extends AbstractWebScript
|
|||||||
switch (method)
|
switch (method)
|
||||||
{
|
{
|
||||||
case LASTMODIFIED:
|
case LASTMODIFIED:
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException("Remote Store expecting document path.");
|
||||||
|
}
|
||||||
lastModified(res, path);
|
lastModified(res, path);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HAS:
|
case HAS:
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException("Remote Store expecting document path.");
|
||||||
|
}
|
||||||
hasDocument(res, path);
|
hasDocument(res, path);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GET:
|
case GET:
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException("Remote Store expecting document path.");
|
||||||
|
}
|
||||||
getDocument(res, path);
|
getDocument(res, path);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LIST:
|
||||||
|
listDocuments(res, path, false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LISTALL:
|
||||||
|
listDocuments(res, path, true);
|
||||||
|
|
||||||
case CREATE:
|
case CREATE:
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException("Remote Store expecting document path.");
|
||||||
|
}
|
||||||
createDocument(res, path, httpReq.getInputStream());
|
createDocument(res, path, httpReq.getInputStream());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException("Remote Store expecting document path.");
|
||||||
|
}
|
||||||
updateDocument(res, path, httpReq.getInputStream());
|
updateDocument(res, path, httpReq.getInputStream());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -193,31 +221,50 @@ public abstract class BaseRemoteStore extends AbstractWebScript
|
|||||||
/**
|
/**
|
||||||
* Gets the last modified timestamp for the document.
|
* Gets the last modified timestamp for the document.
|
||||||
*
|
*
|
||||||
|
* The output will be the last modified date as a long toString().
|
||||||
|
*
|
||||||
* @param path document path to an existing document
|
* @param path document path to an existing document
|
||||||
*/
|
*/
|
||||||
protected abstract void lastModified(WebScriptResponse res, String path)
|
protected abstract void lastModified(WebScriptResponse res, String path)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the document exists
|
* Determines if the document exists.
|
||||||
|
*
|
||||||
|
* The output will be either the string "true" or the string "false".
|
||||||
*
|
*
|
||||||
* @param path document path
|
* @param path document path
|
||||||
* @return true => exists, false => does not exist
|
|
||||||
*/
|
*/
|
||||||
protected abstract void hasDocument(WebScriptResponse res, String path)
|
protected abstract void hasDocument(WebScriptResponse res, String path)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a document
|
* Gets a document.
|
||||||
|
*
|
||||||
|
* The output will be the document content stream.
|
||||||
*
|
*
|
||||||
* @param path document path
|
* @param path document path
|
||||||
* @return input stream onto document
|
* @return
|
||||||
*
|
*
|
||||||
* @throws IOException if the document does not exist in the store
|
* @throws IOException if the document does not exist in the store
|
||||||
*/
|
*/
|
||||||
protected abstract void getDocument(WebScriptResponse res, String path)
|
protected abstract void getDocument(WebScriptResponse res, String path)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists the document paths under a given path.
|
||||||
|
*
|
||||||
|
* The output will be the list of relative document paths found under the path.
|
||||||
|
* Separated by newline characters.
|
||||||
|
*
|
||||||
|
* @param path document path
|
||||||
|
* @param recurse true to peform a recursive list, false for direct children only.
|
||||||
|
*
|
||||||
|
* @throws IOException if the path does not exist in the store
|
||||||
|
*/
|
||||||
|
protected abstract void listDocuments(WebScriptResponse res, String path, boolean recurse)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a document.
|
* Creates a document.
|
||||||
*
|
*
|
||||||
@@ -247,6 +294,8 @@ public abstract class BaseRemoteStore extends AbstractWebScript
|
|||||||
LASTMODIFIED,
|
LASTMODIFIED,
|
||||||
HAS,
|
HAS,
|
||||||
GET,
|
GET,
|
||||||
|
LIST,
|
||||||
|
LISTALL,
|
||||||
CREATE,
|
CREATE,
|
||||||
UPDATE
|
UPDATE
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user