From 4af2f1fa50133f5b2bad87d1411b982aea4f32f9 Mon Sep 17 00:00:00 2001 From: Mark Rogers Date: Tue, 22 Jul 2014 13:00:01 +0000 Subject: [PATCH] Merged HEAD-BUG-FIX (5.0/Cloud) to HEAD (5.0/Cloud) 75556: Merged EOL to HEAD-BUG-FIX (5.0/Cloud) 74583: ACE-2010 EOL Legacey CMIS Inputs (2) in 5.0 << Broken >> - With Kevin - try and bring back ContentGet/ContentInfo so need ReferenceFactory 75109: ACE-2010 - EOL Legacey CMIS Inputs (2) in 5.0. Restored ContentGet and ContentInfo functionality without CMIS related infection. 75110: ACE-2010 - EOL Legacey CMIS Inputs (2) in 5.0. Move content scripts out of cmis folder so it can be safely removed. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@77490 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/cmis/content.delete.desc.xml | 51 ------ .../org/alfresco/cmis/content.put.desc.xml | 56 ------ .../{cmis => content}/content.get.desc.xml | 30 +--- .../{cmis => content}/content.head.desc.xml | 9 +- .../web-scripts-application-context.xml | 23 ++- .../repo/web/scripts/content/ContentGet.java | 170 ++++++++++++++++++ .../repo/web/scripts/content/ContentInfo.java | 102 +++++++++++ .../web/scripts/content/StreamContent.java | 85 +++++++++ 8 files changed, 388 insertions(+), 138 deletions(-) delete mode 100644 config/alfresco/templates/webscripts/org/alfresco/cmis/content.delete.desc.xml delete mode 100644 config/alfresco/templates/webscripts/org/alfresco/cmis/content.put.desc.xml rename config/alfresco/templates/webscripts/org/alfresco/{cmis => content}/content.get.desc.xml (50%) rename config/alfresco/templates/webscripts/org/alfresco/{cmis => content}/content.head.desc.xml (74%) create mode 100644 source/java/org/alfresco/repo/web/scripts/content/ContentGet.java create mode 100644 source/java/org/alfresco/repo/web/scripts/content/ContentInfo.java diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.delete.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/cmis/content.delete.desc.xml deleted file mode 100644 index b4d7a15fac..0000000000 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.delete.desc.xml +++ /dev/null @@ -1,51 +0,0 @@ - - Delete Content (deleteContent) - - - - - - /cmis/i/{id}/content{property} - /cmis/s/{store}/i/{id}/content{property} - - /cmis/p{path}/content{property} - /cmis/s/{store}/p{path}/content{property} - - /api/node/content{property}/{store_type}/{store_id}/{id} - /api/path/content{property}/{store_type}/{store_id}/{nodepath} - /api/avmpath/content{property}/{store_id}/{id} - /api/node/{store_type}/{store_id}/{id}/content{property} - /api/path/{store_type}/{store_id}/{nodepath}/content{property} - - - - store - the store name - - - id - the node id of the object - - - path - the path of the object (relative to CMIS root, typically "Company Home") - - - nodepath - the path of the object (relative to root of Alfresco store) - - - property - the name of the content property to retrieve content from - cm:content - - - - argument - - guest - CMIS - deprecated - \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.put.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/cmis/content.put.desc.xml deleted file mode 100644 index ea998992a5..0000000000 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.put.desc.xml +++ /dev/null @@ -1,56 +0,0 @@ - - Write Content (setContent) - - - - - - /cmis/i/{id}/content{property}?overwriteFlag={overwriteFlag?} - /cmis/s/{store}/i/{id}/content{property}?overwriteFlag={overwriteFlag?} - - /cmis/p{path}/content{property}?overwriteFlag={overwriteFlag?} - /cmis/s/{store}/p{path}/content{property}?overwriteFlag={overwriteFlag?} - - /api/node/content{property}/{store_type}/{store_id}/{id}?overwriteFlag={overwriteFlag?} - /api/path/content{property}/{store_type}/{store_id}/{nodepath}?overwriteFlag={overwriteFlag?} - /api/avmpath/content{property}/{store_id}/{id}?overwriteFlag={overwriteFlag?} - /api/node/{store_type}/{store_id}/{id}/content{property}?overwriteFlag={overwriteFlag?} - /api/path/{store_type}/{store_id}/{nodepath}/content{property}?overwriteFlag={overwriteFlag?} - - - - store - the store name - - - id - the node id of the object - - - path - the path of the object (relative to CMIS root, typically "Company Home") - - - nodepath - the path of the object (relative to root of Alfresco store) - - - property - the name of the content property to retrieve content from - cm:content - - - overwriteFlag - if true, force download of content as attachment - true - - - - argument - - guest - CMIS - deprecated - \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/content/content.get.desc.xml similarity index 50% rename from config/alfresco/templates/webscripts/org/alfresco/cmis/content.get.desc.xml rename to config/alfresco/templates/webscripts/org/alfresco/content/content.get.desc.xml index bccd2bb6e8..c731856e7b 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.get.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/content/content.get.desc.xml @@ -2,23 +2,14 @@ Get Content (getContent) - - /cmis/i/{id}/content{property}?a={attach?}&streamId={streamId?} - /cmis/s/{store}/i/{id}/content{property}?a={attach?}&streamId={streamId?} - - /cmis/p{path}/content{property}?a={attach?}&streamId={streamId?} - /cmis/s/{store}/p{path}/content{property}?a={attach?}&streamId={streamId?} - - - /api/node/content{property}/{store_type}/{store_id}/{id}?a={attach?}&streamId={streamId?} - /api/path/content{property}/{store_type}/{store_id}/{nodepath}?a={attach?}&streamId={streamId?} - /api/avmpath/content{property}/{store_id}/{avmpath}?a={attach?}&streamId={streamId?} - /api/node/{store_type}/{store_id}/{id}/content{property}?a={attach?}&streamId={streamId?} - /api/path/{store_type}/{store_id}/{nodepath}/content{property}?a={attach?}&streamId={streamId?} + /api/node/content{property}/{store_type}/{store_id}/{id}?a={attach?} + /api/path/content{property}/{store_type}/{store_id}/{nodepath}?a={attach?} + /api/node/{store_type}/{store_id}/{id}/content{property}?a={attach?} + /api/path/{store_type}/{store_id}/{nodepath}/content{property}?a={attach?} @@ -29,10 +20,6 @@ id the node id of the object - - path - the path of the object (relative to CMIS root, typically "Company Home") - nodepath the path of the object (relative to root of Alfresco store) @@ -47,16 +34,11 @@ if true, force download of content as attachment false - - streamId - if provided, download the rendition of the content as identified by the stream id - argument guest - CMIS - deprecated + internal \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.head.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/content/content.head.desc.xml similarity index 74% rename from config/alfresco/templates/webscripts/org/alfresco/cmis/content.head.desc.xml rename to config/alfresco/templates/webscripts/org/alfresco/content/content.head.desc.xml index 6239aef9ac..afa806249e 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.head.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/content/content.head.desc.xml @@ -1,10 +1,10 @@ Head Content - Head method for the specified document. + HEAD method for the specified document. - /api/node/content{property}/{store_type}/{store_id}/{id}?a={attach?}&streamId={streamId?} + /api/node/content{property}/{store_type}/{store_id}/{id}?a={attach?} @@ -21,13 +21,10 @@ if true, force download of content as attachment false - - streamId - if provided, download the rendition of the content as identified by the stream id - argument guest + internal \ 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 65fea8e4b9..2466307af1 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -282,6 +282,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -299,7 +320,7 @@ diff --git a/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java b/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java new file mode 100644 index 0000000000..46ee8f8660 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.web.scripts.content; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.web.context.ServletContextAware; + + +/** + * Content Retrieval Service + * + * Stream content from the Repository. + * + * @author davidc + */ +public class ContentGet extends StreamContent implements ServletContextAware +{ + // Logger + @SuppressWarnings("unused") + private static final Log logger = LogFactory.getLog(ContentGet.class); + + // Component dependencies + private ServletContext servletContext; + private DictionaryService dictionaryService; + private NamespaceService namespaceService; + private ContentService contentService; + + /** + * @param + */ + public void setServletContext(ServletContext servletContext) + { + this.servletContext = servletContext; + } + + /** + * @param dictionaryService + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * @param namespaceService + */ + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + /** + * @param contentService + */ + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + /** + * @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 + { + // create map of args + String[] names = req.getParameterNames(); + Map args = new HashMap(names.length, 1.0f); + for (String name : names) + { + args.put(name, req.getParameter(name)); + } + + // create map of template vars + Map templateVars = req.getServiceMatch().getTemplateVars(); + + // create object reference from url + ObjectReference reference = createObjectReferenceFromUrl(args, templateVars); + NodeRef nodeRef = reference.getNodeRef(); + if (nodeRef == null) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString()); + } + + // determine attachment + boolean attach = Boolean.valueOf(req.getParameter("a")); + + // render content + QName propertyQName = ContentModel.PROP_CONTENT; + String contentPart = templateVars.get("property"); + 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) + { + propertyQName = QName.createQName(propertyName, namespaceService); + } + } + + // Stream the content + streamContentLocal(req, res, nodeRef, attach, propertyQName); + } + + private void streamContentLocal(WebScriptRequest req, WebScriptResponse res, NodeRef nodeRef, boolean attach, QName propertyQName) throws IOException + { + String userAgent = req.getHeader("User-Agent"); + + boolean rfc5987Supported = (null != userAgent) && (userAgent.contains("MSIE") || userAgent.contains(" Chrome/") || userAgent.contains(" FireFox/")); + + if (attach && rfc5987Supported) + { + String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); + + //IE use file extension to get mimetype + //So we set correct extension. see MNT-11246 + if(userAgent.contains("MSIE")) + { + String mimeType = contentService.getReader(nodeRef, propertyQName).getMimetype(); + if (!mimetypeService.getMimetypes(FilenameUtils.getExtension(name)).contains(mimeType)) + { + name = FilenameUtils.removeExtension(name) + FilenameUtils.EXTENSION_SEPARATOR_STR + mimetypeService.getExtension(mimeType); + } + } + + streamContent(req, res, nodeRef, propertyQName, attach, name, null); + } + else + { + streamContent(req, res, nodeRef, propertyQName, attach, null, null); + } + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/content/ContentInfo.java b/source/java/org/alfresco/repo/web/scripts/content/ContentInfo.java new file mode 100644 index 0000000000..a0973a72fb --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/content/ContentInfo.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.web.scripts.content; + +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + * Content Info Service Get info about content from the Repository. + * + * @author alex.malinovsky + */ +public class ContentInfo extends StreamContent +{ + @Override + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + // create empty map of args + Map args = new HashMap(0, 1.0f); + // create map of template vars + Map templateVars = req.getServiceMatch().getTemplateVars(); + // create object reference from url + ObjectReference reference = createObjectReferenceFromUrl(args, templateVars); + NodeRef nodeRef = reference.getNodeRef(); + if (nodeRef == null) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString()); + } + + // render content + QName propertyQName = ContentModel.PROP_CONTENT; + + // Stream the content + streamContent(req, res, nodeRef, propertyQName, false, null, null); + } + + protected void streamContentImpl(WebScriptRequest req, WebScriptResponse res, + ContentReader reader, NodeRef nodeRef, QName propertyQName, + boolean attach, Date modified, String eTag, String attachFileName) + throws IOException + { + delegate.setAttachment(req, res, attach, attachFileName); + + // establish mimetype + String mimetype = reader.getMimetype(); + String extensionPath = req.getExtensionPath(); + if (mimetype == null || mimetype.length() == 0) + { + mimetype = MimetypeMap.MIMETYPE_BINARY; + int extIndex = extensionPath.lastIndexOf('.'); + if (extIndex != -1) + { + String ext = extensionPath.substring(extIndex + 1); + mimetype = mimetypeService.getMimetype(ext); + } + } + + // set mimetype for the content and the character encoding + length for the stream + res.setContentType(mimetype); + res.setContentEncoding(reader.getEncoding()); + res.setHeader("Content-Length", Long.toString(reader.getSize())); + + // set caching + Cache cache = new Cache(); + cache.setNeverCache(false); + cache.setMustRevalidate(true); + cache.setMaxAge(0L); + cache.setLastModified(modified); + cache.setETag(eTag); + res.setCache(cache); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java b/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java index d79b47b02d..3430904d28 100644 --- a/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java +++ b/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java @@ -26,10 +26,12 @@ import java.util.HashMap; import java.util.Map; import org.alfresco.model.ContentModel; +import org.alfresco.repo.model.Repository; import org.alfresco.service.cmr.repository.ContentReader; 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.repository.StoreRef; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; @@ -61,6 +63,7 @@ public class StreamContent extends AbstractWebScript protected NodeService nodeService; protected MimetypeService mimetypeService; protected ContentStreamer delegate; + protected Repository repository; /** * @param mimetypeService @@ -93,6 +96,14 @@ public class StreamContent extends AbstractWebScript this.delegate = delegate; } + /** + * @param repository + */ + public void setRepository(Repository repository) + { + this.repository = repository; + } + /** * @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) */ @@ -366,4 +377,78 @@ public class StreamContent extends AbstractWebScript renderTemplate(templatePath, model, writer); } + protected ObjectReference createObjectReferenceFromUrl(Map args, Map templateArgs) + { + String objectId = args.get("noderef"); + if (objectId != null) + { + return new ObjectReference(objectId); + } + + StoreRef storeRef = null; + String store_type = templateArgs.get("store_type"); + String store_id = templateArgs.get("store_id"); + if (store_type != null && store_id != null) + { + storeRef = new StoreRef(store_type, store_id); + } + + String id = templateArgs.get("id"); + if (storeRef != null && id != null) + { + return new ObjectReference(storeRef, id); + } + + String nodepath = templateArgs.get("nodepath"); + if (nodepath == null) + { + nodepath = args.get("nodepath"); + } + if (storeRef != null && nodepath != null) + { + return new ObjectReference(storeRef, nodepath.split("/")); + } + + return null; + } + + + class ObjectReference + { + private NodeRef ref; + + ObjectReference(String nodeRef) + { + this.ref = new NodeRef(nodeRef); + } + + ObjectReference(StoreRef ref, String id) + { + if (id.indexOf('/') != -1) + { + id = id.substring(0, id.indexOf('/')); + } + this.ref = new NodeRef(ref, id); + } + + ObjectReference(StoreRef ref, String[] path) + { + String[] reference = new String[path.length + 2]; + reference[0] = ref.getProtocol(); + reference[1] = ref.getIdentifier(); + System.arraycopy(path, 0, reference, 2, path.length); + this.ref = repository.findNodeRef("path", reference); + } + + public NodeRef getNodeRef() + { + return this.ref; + } + + @Override + public String toString() + { + return ref != null ? ref.toString() : super.toString(); + } + } }