diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index 9fe85d1a85..85c3b2ef79 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -248,18 +248,21 @@ + alfresco sitestore + alfresco sitestore + alfresco sitestore diff --git a/source/java/org/alfresco/repo/web/scripts/bean/AVMRemoteStore.java b/source/java/org/alfresco/repo/web/scripts/bean/AVMRemoteStore.java index ba6f0ff119..b048fa0afb 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/AVMRemoteStore.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/AVMRemoteStore.java @@ -28,13 +28,16 @@ import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.net.SocketException; +import java.util.List; import java.util.SortedMap; +import java.util.regex.Pattern; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.repo.web.scripts.RepoStore; import org.alfresco.service.cmr.avm.AVMExistsException; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMNotFoundException; @@ -42,6 +45,10 @@ import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchService; import org.alfresco.web.scripts.Status; import org.alfresco.web.scripts.WebScriptException; import org.alfresco.web.scripts.WebScriptResponse; @@ -62,6 +69,7 @@ public class AVMRemoteStore extends BaseRemoteStore private String rootPath; private AVMService avmService; + private SearchService searchService; /** @@ -80,7 +88,14 @@ public class AVMRemoteStore extends BaseRemoteStore this.avmService = avmService; } - + /** + * @param searchService the SearchService to set + */ + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + /** * Gets the last modified timestamp for the document. * @@ -229,8 +244,9 @@ public class AVMRemoteStore extends BaseRemoteStore parentPath = dirPath; index++; } - + avmService.createFile(parts[0], parts[1], content); + avmService.createSnapshot(store, "AVMRemoteStore.createDocument()", path); } catch (AccessDeniedException ae) { @@ -300,6 +316,7 @@ public class AVMRemoteStore extends BaseRemoteStore try { avmService.removeNode(avmPath); + avmService.createSnapshot(store, "AVMRemoteStore.deleteDocument()", path); } catch (AccessDeniedException ae) { @@ -356,6 +373,67 @@ public class AVMRemoteStore extends BaseRemoteStore } } } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.scripts.bean.BaseRemoteStore#listDocuments(org.alfresco.web.scripts.WebScriptResponse, java.lang.String, java.lang.String) + */ + @Override + protected void listDocuments(WebScriptResponse res, String path, String pattern) throws IOException + { + String avmPath = buildAVMPath(path); + AVMNodeDescriptor node = this.avmService.lookup(-1, avmPath); + if (node == null) + { + res.setStatus(Status.STATUS_NOT_FOUND); + return; + } + + if (pattern == null || pattern.length() == 0) + { + pattern = "*"; + } + + String matcher = pattern.replace(".","\\.").replace("*",".*"); + final Pattern pat = Pattern.compile(matcher); + + String encPath = RepoStore.encodePathISO9075(path); + final StringBuilder query = new StringBuilder(128); + query.append("+PATH:\"/").append(this.rootPath) + .append(encPath.length() != 0 ? ('/' + encPath) : "") + .append("//*\" +QNAME:") + .append(pattern); + + final Writer out = res.getWriter(); + final StoreRef avmStore = new StoreRef(StoreRef.PROTOCOL_AVM + StoreRef.URI_FILLER + this.store); + AuthenticationUtil.runAs(new RunAsWork() + { + @SuppressWarnings("synthetic-access") + public Object doWork() throws Exception + { + int cropPoint = store.length() + rootPath.length() + 3; + ResultSet resultSet = searchService.query(avmStore, SearchService.LANGUAGE_LUCENE, query.toString()); + try + { + List nodes = resultSet.getNodeRefs(); + for (NodeRef nodeRef : nodes) + { + String path = AVMNodeConverter.ToAVMVersionPath(nodeRef).getSecond(); + String name = path.substring(path.lastIndexOf('/') + 1); + if (pat.matcher(name).matches()) + { + out.write(path.substring(cropPoint)); + out.write("\n"); + } + } + } + finally + { + resultSet.close(); + } + return null; + } + }, AuthenticationUtil.getSystemUserName()); + } /** * @param path root path relative diff --git a/source/java/org/alfresco/repo/web/scripts/bean/BaseRemoteStore.java b/source/java/org/alfresco/repo/web/scripts/bean/BaseRemoteStore.java index 0cf1641834..538b59245a 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/BaseRemoteStore.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/BaseRemoteStore.java @@ -48,7 +48,7 @@ import org.apache.commons.logging.LogFactory; * from a web-tier application to remotely mirror a WebScript Store instance. * * Request format: - * // + * //[?] * * Example: * /service/remotestore/lastmodified/sites/xyz/pages/page.xml @@ -60,6 +60,8 @@ import org.apache.commons.logging.LogFactory; * * Note: path is relative to the root path as configured for this webscript bean * + * Further URL arguments may be provided if required by specific API methods. + * * For content create and update the request should be POSTed and the content sent as the * payload of the request content. * @@ -70,6 +72,7 @@ import org.apache.commons.logging.LogFactory; * 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 + * GET listpattern -> return the list of document paths matching a file pattern under a given path * POST create -> create a new document with request content payload * POST update -> update an existing document with request content payload * DELETE delete -> delete an existing document @@ -140,7 +143,7 @@ public abstract class BaseRemoteStore extends AbstractWebScript if (logger.isDebugEnabled()) logger.debug("Remote store method: " + extParts[0] + " path: " + path); - // TODO: support storeref name override as argument (i.e. for AVM virtualisation) + // TODO: support storeref name override as argument? (i.e. for AVM virtualisation) try { @@ -169,6 +172,11 @@ public abstract class BaseRemoteStore extends AbstractWebScript case LISTALL: listDocuments(res, path, true); + break; + + case LISTPATTERN: + listDocuments(res, path, req.getParameter("m")); + break; case CREATE: validatePath(path); @@ -267,6 +275,20 @@ public abstract class BaseRemoteStore extends AbstractWebScript protected abstract void listDocuments(WebScriptResponse res, String path, boolean recurse) throws IOException; + /** + * Lists the document paths matching a file pattern under a given path. + * + * The output will be the list of relative document paths found under the path that + * match the given file pattern. Separated by newline characters. + * + * @param path document path + * @param pattern file pattern to match - allows wildcards e.g. *.xml or site*.xml + * + * @throws IOException if an error occurs listing the documents + */ + protected abstract void listDocuments(WebScriptResponse res, String path, String pattern) + throws IOException; + /** * Creates a document. * @@ -307,6 +329,7 @@ public abstract class BaseRemoteStore extends AbstractWebScript GET, LIST, LISTALL, + LISTPATTERN, CREATE, UPDATE, DELETE