diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.atom.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.atom.ftl similarity index 96% rename from config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.atom.ftl rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.atom.ftl index 927afc6d27..0bddfbcdca 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.atom.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.atom.ftl @@ -26,7 +26,7 @@ <#list search.results as row> ${row.name} - + ${absurl(url.context)}${row.icon16} <#comment>TODO: What's the standard for entry icons? urn:uuid:${row.id} ${row.nodeRef} diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.desc.xml similarity index 100% rename from config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.desc.xml rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.desc.xml diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.html.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.html.ftl similarity index 86% rename from config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.html.ftl rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.html.ftl index 5da47307a0..f2a7c0acac 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.html.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.html.ftl @@ -19,14 +19,14 @@
- +
Results ${search.startIndex} - ${search.startIndex + search.totalPageItems - 1} of ${search.totalResults} for ${search.searchTerms} visible to user <#if person??>${person.properties.userName}<#else>unknown.Results ${search.startIndex} - <#if search.startIndex == 0>0<#else>${search.startIndex + search.totalPageItems - 1} of ${search.totalResults} for ${search.searchTerms} visible to user <#if person??>${person.properties.userName}<#else>unknown.

<#list search.results as row> - + <#if row.properties.description?? == true> diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.portlet.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.portlet.ftl similarity index 96% rename from config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.portlet.ftl rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.portlet.ftl index 259e749fc5..7ef3004391 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.portlet.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.portlet.ftl @@ -7,7 +7,7 @@
${row.name}${row.name}
<#list search.results as row> - + <#if row.properties.description?? == true> diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.query_.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.query_.ftl similarity index 100% rename from config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.query_.ftl rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.query_.ftl diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.rss.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.rss.ftl similarity index 96% rename from config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.rss.ftl rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.rss.ftl index 79b55075b6..25d1c2e585 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearch.get.rss.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearch.get.rss.ftl @@ -31,7 +31,7 @@ <#list search.results as row> ${row.name} - ${absurl(url.context)}${row.url} + ${absurl(url.serviceContext)}${row.url} ${row.properties.description!""} ${xmldate(row.properties.modified)} ${row.id} diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearchdescription.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearchdescription.get.desc.xml similarity index 100% rename from config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearchdescription.get.desc.xml rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearchdescription.get.desc.xml diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearchdescription.get.opensearchdescription.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearchdescription.get.opensearchdescription.ftl similarity index 100% rename from config/alfresco/templates/webscripts/org/alfresco/repository/keywordsearchdescription.get.opensearchdescription.ftl rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/keywordsearchdescription.get.opensearchdescription.ftl diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/searchengines.get.atom.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/search/searchengines.get.atom.ftl similarity index 100% rename from config/alfresco/templates/webscripts/org/alfresco/repository/searchengines.get.atom.ftl rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/searchengines.get.atom.ftl diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/searchengines.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/search/searchengines.get.desc.xml similarity index 100% rename from config/alfresco/templates/webscripts/org/alfresco/repository/searchengines.get.desc.xml rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/searchengines.get.desc.xml diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/searchengines.get.html.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/search/searchengines.get.html.ftl similarity index 100% rename from config/alfresco/templates/webscripts/org/alfresco/repository/searchengines.get.html.ftl rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/searchengines.get.html.ftl diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/searchproxy.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/search/searchproxy.get.desc.xml similarity index 100% rename from config/alfresco/templates/webscripts/org/alfresco/repository/searchproxy.get.desc.xml rename to config/alfresco/templates/webscripts/org/alfresco/repository/search/searchproxy.get.desc.xml diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/store/content.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/store/content.get.desc.xml new file mode 100644 index 0000000000..500d05b198 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/store/content.get.desc.xml @@ -0,0 +1,8 @@ + + Content Retrieval + Stream a content property from the Repository + /api/node/content{;property}/{store_type}/{store_id}/{node_id}?a={attach?} + /api/path/content{;property}/{store_type}/{store_id}/{path}?a={attach?} + guest + argument + \ No newline at end of file diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index d4ec3d9e94..69bcdf6872 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -191,6 +191,9 @@ + + + @@ -203,24 +206,24 @@ - - - - + - + - + - + + + + diff --git a/source/java/org/alfresco/web/app/servlet/ExternalAccessServlet.java b/source/java/org/alfresco/web/app/servlet/ExternalAccessServlet.java index 7f60d45f54..5fc775e242 100644 --- a/source/java/org/alfresco/web/app/servlet/ExternalAccessServlet.java +++ b/source/java/org/alfresco/web/app/servlet/ExternalAccessServlet.java @@ -28,8 +28,14 @@ import java.io.IOException; import java.text.MessageFormat; import java.util.StringTokenizer; +import javax.faces.FactoryFinder; import javax.faces.application.NavigationHandler; +import javax.faces.application.ViewHandler; +import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; +import javax.faces.context.FacesContextFactory; +import javax.faces.lifecycle.Lifecycle; +import javax.faces.lifecycle.LifecycleFactory; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -253,6 +259,10 @@ public class ExternalAccessServlet extends BaseServlet // perform the appropriate JSF navigation outcome NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler(); navigationHandler.handleNavigation(fc, null, outcome); + LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); + Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE); + lifecycle.render(fc); + return; } else if (OUTCOME_DIALOG.equals(outcome) || OUTCOME_WIZARD.equals(outcome)) { diff --git a/source/java/org/alfresco/web/scripts/AbstractWebScript.java b/source/java/org/alfresco/web/scripts/AbstractWebScript.java index 68a23032b9..7b4e9502fa 100644 --- a/source/java/org/alfresco/web/scripts/AbstractWebScript.java +++ b/source/java/org/alfresco/web/scripts/AbstractWebScript.java @@ -26,6 +26,7 @@ package org.alfresco.web.scripts; import java.io.IOException; import java.io.Writer; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -37,8 +38,13 @@ import org.alfresco.repo.jscript.ScriptNode; import org.alfresco.repo.jscript.ScriptableHashMap; import org.alfresco.repo.template.AbsoluteUrlMethod; import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.model.FileNotFoundException; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.ScriptLocation; +import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.TemplateService; import org.alfresco.service.descriptor.DescriptorService; import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication; @@ -518,6 +524,84 @@ public abstract class AbstractWebScript implements WebScript getWebScriptRegistry().getScriptProcessor().executeScript(location, model); } + /** + * Helper to convert a Web Script Request URL to a Node Ref + * + * 1) Node - {store_type}/{store_id}/{node_id} + * + * Resolve to node via its Node Reference. + * + * 2) Path - {store_type}/{store_id}/{path} + * + * Resolve to node via its display path. + * + * 3) QName - {store_type}/{store_id}/{child_qname_path} TODO: Implement + * + * Resolve to node via its child qname path. + * + * @param referenceType one of node, path or qname + * @return reference array of reference segments (as described above for each reference type) + */ + protected NodeRef findNodeRef(String referenceType, String[] reference) + { + NodeRef nodeRef = null; + + // construct store reference + if (reference.length < 3) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Reference " + Arrays.toString(reference) + " is not properly formed"); + } + StoreRef storeRef = new StoreRef(reference[0], reference[1]); + NodeService nodeService = serviceRegistry.getNodeService(); + if (nodeService.exists(storeRef)) + { + if (referenceType.equals("node")) + { + NodeRef urlRef = new NodeRef(storeRef, reference[2]); + if (nodeService.exists(urlRef)) + { + nodeRef = urlRef; + } + } + + else if (referenceType.equals("path")) + { + // TODO: Allow a root path to be specified - for now, hard-code to Company Home +// NodeRef rootNodeRef = nodeService.getRootNode(storeRef); + NodeRef rootNodeRef = getRepositoryContext().getCompanyHome(); + if (reference.length == 3) + { + nodeRef = rootNodeRef; + } + else + { + String[] path = new String[reference.length - /*2*/3]; + System.arraycopy(reference, /*2*/3, path, 0, path.length); + + try + { + FileFolderService ffService = serviceRegistry.getFileFolderService(); + FileInfo fileInfo = ffService.resolveNamePath(rootNodeRef, Arrays.asList(path)); + nodeRef = fileInfo.getNodeRef(); + } + catch (FileNotFoundException e) + { + // NOTE: return null node ref + } + } + } + + else + { + // TODO: Implement 'qname' style + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script Node URL specified an invalid reference style of '" + referenceType + "'"); + } + } + + return nodeRef; + } + + /** * Status Template */ diff --git a/source/java/org/alfresco/web/scripts/TestWebScriptServer.java b/source/java/org/alfresco/web/scripts/TestWebScriptServer.java index 7c1137a569..8437f4e02b 100644 --- a/source/java/org/alfresco/web/scripts/TestWebScriptServer.java +++ b/source/java/org/alfresco/web/scripts/TestWebScriptServer.java @@ -32,6 +32,8 @@ import java.io.InputStreamReader; import java.io.PrintStream; import java.io.PrintWriter; import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.util.HashMap; import java.util.Map; @@ -498,8 +500,10 @@ public class TestWebScriptServer * @param method * @param uri * @return mock http servlet request + * @throws UnsupportedEncodingException */ private MockHttpServletRequest createRequest(String method, String uri) + throws UnsupportedEncodingException { MockHttpServletRequest req = new MockHttpServletRequest(method, uri); @@ -516,10 +520,11 @@ public class TestWebScriptServer for (String arg : args) { String[] parts = arg.split("="); - req.addParameter(parts[0], (parts.length == 2) ? parts[1] : null); + req.addParameter(parts[0], (parts.length == 2) ? URLDecoder.decode(parts[1], "UTF-8") : null); } } - req.setPathInfo(iArgIndex == -1 ? uri : uri.substring(0, iArgIndex)); + String pathInfo = iArgIndex == -1 ? uri : uri.substring(0, iArgIndex); + req.setPathInfo(URLDecoder.decode(pathInfo, "UTF-8")); } return req; diff --git a/source/java/org/alfresco/web/scripts/WebScriptRequestImpl.java b/source/java/org/alfresco/web/scripts/WebScriptRequestImpl.java index 637fe371b5..e55df3cfc7 100644 --- a/source/java/org/alfresco/web/scripts/WebScriptRequestImpl.java +++ b/source/java/org/alfresco/web/scripts/WebScriptRequestImpl.java @@ -43,16 +43,11 @@ public abstract class WebScriptRequestImpl implements WebScriptRequest WebScriptMatch match = getServiceMatch(); if (match != null) { - String servicePath = getServiceMatch().getPath(); - extensionPath = getPathInfo(); - if (extensionPath != null) + String matchPath = getServiceMatch().getPath(); + String pathInfo = getPathInfo(); + if (pathInfo != null) { - int extIdx = extensionPath.indexOf(servicePath); - if (extIdx != -1) - { - int extLength = (servicePath.endsWith("/") ? servicePath.length() : servicePath.length() + 1); - extensionPath = extensionPath.substring(extIdx + extLength); - } + extensionPath = pathInfo.substring(matchPath.length()); } } return extensionPath; diff --git a/source/java/org/alfresco/web/scripts/bean/ContentGet.java b/source/java/org/alfresco/web/scripts/bean/ContentGet.java new file mode 100644 index 0000000000..e1bab8987d --- /dev/null +++ b/source/java/org/alfresco/web/scripts/bean/ContentGet.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.web.scripts.bean; + +import java.io.IOException; +import java.net.SocketException; +import java.util.Arrays; +import java.util.Date; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.service.cmr.repository.ContentIOException; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.web.scripts.AbstractWebScript; +import org.alfresco.web.scripts.WebScriptException; +import org.alfresco.web.scripts.WebScriptRequest; +import org.alfresco.web.scripts.WebScriptResponse; +import org.alfresco.web.scripts.WebScriptServletRequest; +import org.alfresco.web.scripts.WebScriptServletResponse; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Content Retrieval Service + * + * Stream content from the Repository. + * + * @author davidc + */ +public class ContentGet extends AbstractWebScript +{ + // Logger + private static final Log logger = LogFactory.getLog(ContentGet.class); + + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) + */ + public void execute(WebScriptRequest req, WebScriptResponse res) + throws IOException + { + // NOTE: This web script must be executed in a HTTP Servlet environment + if (!(req instanceof WebScriptServletRequest)) + { + throw new WebScriptException("Content retrieval must be executed in HTTP Servlet environment"); + } + HttpServletRequest httpReq = ((WebScriptServletRequest)req).getHttpServletRequest(); + HttpServletResponse httpRes = ((WebScriptServletResponse)res).getHttpServletResponse(); + + // convert web script URL to node reference in Repository + String match = req.getServiceMatch().getPath(); + String[] matchParts = match.split("/"); + String extensionPath = req.getExtensionPath(); + String[] extParts = extensionPath == null ? new String[1] : extensionPath.split("/"); + String[] path = new String[extParts.length -1]; + System.arraycopy(extParts, 1, path, 0, extParts.length -1); + NodeRef nodeRef = findNodeRef(matchParts[2], path); + if (nodeRef == null) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + matchParts[2] + " reference " + Arrays.toString(path)); + } + + // determine content property + QName propertyQName = ContentModel.PROP_CONTENT; + String contentPart = extParts[0]; + if (contentPart.length() > 0 && contentPart.charAt(0) == ';') + { + if (contentPart.length() < 2) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Content property malformed"); + } + String propertyName = contentPart.substring(1); + if (propertyName.length() > 0) + { + NamespaceService namespaceService = getServiceRegistry().getNamespaceService(); + propertyQName = QName.createQName(propertyName, namespaceService); + } + } + + // determine attachment + boolean attach = Boolean.valueOf(req.getParameter("a")); + + if (logger.isDebugEnabled()) + logger.debug("Retrieving content from node ref " + nodeRef.toString() + " (property: " + propertyQName.toString() + ") (attach: " + attach + ")"); + + // check that the user has at least READ_CONTENT access - else redirect to the login page + PermissionService permissionService = getServiceRegistry().getPermissionService(); + if (permissionService.hasPermission(nodeRef, PermissionService.READ_CONTENT) == AccessStatus.DENIED) + { + throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Permission denied"); + } + + // check If-Modified-Since header and set Last-Modified header as appropriate + NodeService nodeService = getServiceRegistry().getNodeService(); + Date modified = (Date)nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED); + long modifiedSince = httpReq.getDateHeader("If-Modified-Since"); + if (modifiedSince > 0L) + { + // round the date to the ignore millisecond value which is not supplied by header + long modDate = (modified.getTime() / 1000L) * 1000L; + if (modDate <= modifiedSince) + { + httpRes.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + return; + } + } + httpRes.setDateHeader("Last-Modified", modified.getTime()); + + // handle attachment + if (attach == true) + { + // set header based on filename - will force a Save As from the browse if it doesn't recognize it + // this is better than the default response of the browser trying to display the contents + httpRes.setHeader("Content-Disposition", "attachment"); + } + + // get the content reader + ContentService contentService = getServiceRegistry().getContentService(); + ContentReader reader = contentService.getReader(nodeRef, propertyQName); + if (reader == null || !reader.exists()) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to locate content for node ref " + nodeRef + " (property: " + propertyQName.toString() + ")"); + } + + // establish mimetype + String mimetype = reader.getMimetype(); + if (mimetype == null || mimetype.length() == 0) + { + MimetypeService mimetypeMap = getServiceRegistry().getMimetypeService(); + mimetype = MimetypeMap.MIMETYPE_BINARY; + int extIndex = extensionPath.lastIndexOf('.'); + if (extIndex != -1) + { + String ext = extensionPath.substring(extIndex + 1); + String mt = mimetypeMap.getMimetypesByExtension().get(ext); + if (mt != null) + { + mimetype = mt; + } + } + } + + // set mimetype for the content and the character encoding for the stream + httpRes.setContentType(mimetype); + httpRes.setCharacterEncoding(reader.getEncoding()); + + // get the content and stream directly to the response output stream + // assuming the repository is capable of streaming in chunks, this should allow large files + // to be streamed directly to the browser response stream. + try + { + reader.getContent(res.getOutputStream()); + } + catch (SocketException e1) + { + // the client cut the connection - our mission was accomplished apart from a little error message + if (logger.isInfoEnabled()) + logger.info("Client aborted stream read:\n\tnode: " + nodeRef + "\n\tcontent: " + reader); + } + catch (ContentIOException e2) + { + if (logger.isInfoEnabled()) + logger.info("Client aborted stream read:\n\tnode: " + nodeRef + "\n\tcontent: " + reader); + } + } + +} \ No newline at end of file diff --git a/source/java/org/alfresco/web/scripts/bean/KeywordSearch.java b/source/java/org/alfresco/web/scripts/bean/KeywordSearch.java index bc9bf09169..9b973bda9a 100644 --- a/source/java/org/alfresco/web/scripts/bean/KeywordSearch.java +++ b/source/java/org/alfresco/web/scripts/bean/KeywordSearch.java @@ -25,7 +25,10 @@ package org.alfresco.web.scripts.bean; import java.io.StringWriter; +import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.net.URLEncoder; +import java.text.MessageFormat; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -34,6 +37,7 @@ import org.alfresco.i18n.I18NUtil; import org.alfresco.repo.template.TemplateNode; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.TemplateException; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; @@ -45,6 +49,7 @@ import org.alfresco.web.scripts.WebScriptRequest; import org.alfresco.web.scripts.WebScriptStatus; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.util.StringUtils; /** @@ -187,10 +192,19 @@ public class KeywordSearch extends DeclarativeWebScript searchResult.setLocale(locale); searchResult.setItemsPerPage(itemsPerPage); searchResult.setStartPage(startPage); - searchResult.setTotalPages(totalPages); searchResult.setTotalResults(totalResults); - searchResult.setStartIndex(((startPage -1) * itemsPerPage) + 1); - searchResult.setTotalPageItems(Math.min(itemsPerPage, totalResults - searchResult.getStartIndex() + 1)); + if (totalResults == 0) + { + searchResult.setTotalPages(0); + searchResult.setStartIndex(0); + searchResult.setTotalPageItems(0); + } + else + { + searchResult.setTotalPages(totalPages); + searchResult.setStartIndex(((startPage -1) * itemsPerPage) + 1); + searchResult.setTotalPageItems(Math.min(itemsPerPage, totalResults - searchResult.getStartIndex() + 1)); + } SearchTemplateNode[] nodes = new SearchTemplateNode[searchResult.getTotalPageItems()]; for (int i = 0; i < searchResult.getTotalPageItems(); i++) { @@ -342,6 +356,8 @@ public class KeywordSearch extends DeclarativeWebScript */ public class SearchTemplateNode extends TemplateNode { + protected final static String URL = "/api/node/content/{0}/{1}/{2}/{3}"; + private static final long serialVersionUID = -1791913270786140012L; private float score; @@ -366,6 +382,26 @@ public class KeywordSearch extends DeclarativeWebScript { return score; } + + /* (non-Javadoc) + * @see org.alfresco.repo.template.BaseContentNode#getUrl() + */ + @Override + public String getUrl() + { + try + { + return MessageFormat.format(URL, new Object[] { + getNodeRef().getStoreRef().getProtocol(), + getNodeRef().getStoreRef().getIdentifier(), + getNodeRef().getId(), + StringUtils.replace(URLEncoder.encode(getName(), "UTF-8"), "+", "%20") } ); + } + catch (UnsupportedEncodingException err) + { + throw new TemplateException("Failed to encode content URL for node: " + getNodeRef(), err); + } + } } } \ No newline at end of file diff --git a/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java b/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java index 933180757f..b0a5e6f10b 100644 --- a/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java +++ b/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java @@ -268,7 +268,7 @@ public class UIOpenSearch extends SelfRenderingComponent ConfigService cfgSvc = (ConfigService)FacesContextUtils. getRequiredWebApplicationContext(context).getBean("webscripts.config"); SearchProxy searchProxy = (SearchProxy)FacesContextUtils. - getRequiredWebApplicationContext(context).getBean("webscript.org.alfresco.repository.searchproxy.get"); + getRequiredWebApplicationContext(context).getBean("webscript.org.alfresco.repository.search.searchproxy.get"); if (cfgSvc != null) { // get the OpenSearch configuration
${row.name}${row.name}