diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/doclink/doclink.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/doclink/doclink.post.desc.xml
index e95ce9b7a4..1f9f6aea3e 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/doclink/doclink.post.desc.xml
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/doclink/doclink.post.desc.xml
@@ -41,12 +41,23 @@
+
+ json
+
+
+
+
json
-
+
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/doclink/doclink.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/doclink/doclink.post.json.ftl
index 321d5972da..9c91406902 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/doclink/doclink.post.json.ftl
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/doclink/doclink.post.json.ftl
@@ -1,5 +1,16 @@
<#escape x as jsonUtils.encodeJSONString(x)>
{
- "linkNodeRef": "${linkNodeRef}"
+ "linkNodes" :
+ [
+ <#list results as result>
+ {
+ "nodeRef" : "${result.nodeRef}"
+ }
+ <#if result_has_next>,#if>
+ #list>
+ ],
+ "successCount": "${successCount}",
+ "failureCount": "${failureCount}",
+ "overallSuccess": "${overallSuccess?c}"
}
#escape>
\ 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 5e2e150b76..6ce6f52f33 100644
--- a/config/alfresco/web-scripts-application-context.xml
+++ b/config/alfresco/web-scripts-application-context.xml
@@ -1846,6 +1846,7 @@
+
+
diff --git a/source/java/org/alfresco/repo/web/scripts/doclink/AbstractDocLink.java b/source/java/org/alfresco/repo/web/scripts/doclink/AbstractDocLink.java
index 8e38144138..43a54bf75e 100644
--- a/source/java/org/alfresco/repo/web/scripts/doclink/AbstractDocLink.java
+++ b/source/java/org/alfresco/repo/web/scripts/doclink/AbstractDocLink.java
@@ -23,122 +23,171 @@
* along with Alfresco. If not, see .
* #L%
*/
-package org.alfresco.repo.web.scripts.doclink;
-
-import java.util.Map;
-import java.util.StringTokenizer;
-
-import org.alfresco.model.ContentModel;
-import org.alfresco.service.cmr.repository.DocumentLinkService;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.site.SiteInfo;
-import org.alfresco.service.cmr.site.SiteService;
-import org.alfresco.util.ParameterCheck;
-import org.alfresco.util.PropertyCheck;
-import org.springframework.extensions.webscripts.DeclarativeWebScript;
-import org.springframework.extensions.webscripts.Status;
-import org.springframework.extensions.webscripts.WebScriptException;
-
-/**
- * This class contains common code for doclink webscripts controllers
- *
- * @author Ana Bozianu
- * @since 5.1
- */
-public abstract class AbstractDocLink extends DeclarativeWebScript
-{
- private static String PARAM_STORE_TYPE = "store_type";
- private static String PARAM_STORE_ID = "store_id";
- private static String PARAM_ID = "id";
- private static String PARAM_SITE = "site";
- private static String PARAM_CONTAINER = "container";
- private static String PARAM_PATH = "path";
-
- protected NodeService nodeService;
- protected SiteService siteService;
- protected DocumentLinkService documentLinkService;
-
- protected NodeRef parseNodeRefFromTemplateArgs(Map templateVars)
- {
- if (templateVars == null)
- {
- return null;
- }
-
- String storeTypeArg = templateVars.get(PARAM_STORE_TYPE);
- String storeIdArg = templateVars.get(PARAM_STORE_ID);
- String idArg = templateVars.get(PARAM_ID);
-
- if (storeTypeArg != null)
- {
- ParameterCheck.mandatoryString("storeTypeArg", storeTypeArg);
- ParameterCheck.mandatoryString("storeIdArg", storeIdArg);
- ParameterCheck.mandatoryString("idArg", idArg);
-
- /*
- * NodeRef based request
- * URL_BASE/{store_type}/{store_id}/{id}
- */
- return new NodeRef(storeTypeArg, storeIdArg, idArg);
- }
- else
- {
- String siteArg = templateVars.get(PARAM_SITE);
- String containerArg = templateVars.get(PARAM_CONTAINER);
- String pathArg = templateVars.get(PARAM_PATH);
-
- if (siteArg != null)
- {
- ParameterCheck.mandatoryString("siteArg", siteArg);
- ParameterCheck.mandatoryString("containerArg", containerArg);
-
- /*
- * Site based request URL_BASE/{site}/{container} or
- * URL_BASE/{site}/{container}/{path}
- */
- SiteInfo site = siteService.getSite(siteArg);
- PropertyCheck.mandatory(this, "site", site);
-
- NodeRef node = siteService.getContainer(site.getShortName(), containerArg);
- if (node == null)
- {
- throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid 'container' variable");
- }
-
- if (pathArg != null)
- {
- // URL_BASE/{site}/{container}/{path}
- StringTokenizer st = new StringTokenizer(pathArg, "/");
- while (st.hasMoreTokens())
- {
- String childName = st.nextToken();
- node = nodeService.getChildByName(node, ContentModel.ASSOC_CONTAINS, childName);
- if (node == null)
- {
- throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid 'path' variable");
- }
- }
- }
-
- return node;
- }
- }
- return null;
- }
-
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- public void setSiteService(SiteService siteService)
- {
- this.siteService = siteService;
- }
-
- public void setDocumentLinkService(DocumentLinkService documentLinkService)
- {
- this.documentLinkService = documentLinkService;
- }
-}
+package org.alfresco.repo.web.scripts.doclink;
+
+import java.io.StringWriter;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.web.scripts.links.AbstractLinksWebScript;
+import org.alfresco.service.cmr.activities.ActivityService;
+import org.alfresco.service.cmr.links.LinkInfo;
+import org.alfresco.service.cmr.repository.DocumentLinkService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.site.SiteInfo;
+import org.alfresco.service.cmr.site.SiteService;
+import org.alfresco.util.ParameterCheck;
+import org.alfresco.util.PropertyCheck;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.JSONStringer;
+import org.json.simple.JSONObject;
+import org.springframework.extensions.webscripts.DeclarativeWebScript;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.WebScriptException;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+import org.springframework.extensions.webscripts.json.JSONWriter;
+
+/**
+ * This class contains common code for doclink webscripts controllers
+ *
+ * @author Ana Bozianu
+ * @since 5.1
+ */
+public abstract class AbstractDocLink extends DeclarativeWebScript
+{
+ private static String PARAM_STORE_TYPE = "store_type";
+ private static String PARAM_STORE_ID = "store_id";
+ private static String PARAM_ID = "id";
+ private static String PARAM_SITE = "site";
+ private static String PARAM_CONTAINER = "container";
+ private static String PARAM_PATH = "path";
+
+ private static final String ACTIVITY_TOOL = "documentLinkService";
+
+ protected NodeService nodeService;
+ protected SiteService siteService;
+ protected DocumentLinkService documentLinkService;
+ protected ActivityService activityService;
+
+ private static Log logger = LogFactory.getLog(AbstractDocLink.class);
+
+ protected NodeRef parseNodeRefFromTemplateArgs(Map templateVars)
+ {
+ if (templateVars == null)
+ {
+ return null;
+ }
+
+ String storeTypeArg = templateVars.get(PARAM_STORE_TYPE);
+ String storeIdArg = templateVars.get(PARAM_STORE_ID);
+ String idArg = templateVars.get(PARAM_ID);
+
+ if (storeTypeArg != null)
+ {
+ ParameterCheck.mandatoryString("storeTypeArg", storeTypeArg);
+ ParameterCheck.mandatoryString("storeIdArg", storeIdArg);
+ ParameterCheck.mandatoryString("idArg", idArg);
+
+ /*
+ * NodeRef based request
+ * URL_BASE/{store_type}/{store_id}/{id}
+ */
+ return new NodeRef(storeTypeArg, storeIdArg, idArg);
+ }
+ else
+ {
+ String siteArg = templateVars.get(PARAM_SITE);
+ String containerArg = templateVars.get(PARAM_CONTAINER);
+ String pathArg = templateVars.get(PARAM_PATH);
+
+ if (siteArg != null)
+ {
+ ParameterCheck.mandatoryString("siteArg", siteArg);
+ ParameterCheck.mandatoryString("containerArg", containerArg);
+
+ /*
+ * Site based request URL_BASE/{site}/{container} or
+ * URL_BASE/{site}/{container}/{path}
+ */
+ SiteInfo site = siteService.getSite(siteArg);
+ PropertyCheck.mandatory(this, "site", site);
+
+ NodeRef node = siteService.getContainer(site.getShortName(), containerArg);
+ if (node == null)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid 'container' variable");
+ }
+
+ if (pathArg != null)
+ {
+ // URL_BASE/{site}/{container}/{path}
+ StringTokenizer st = new StringTokenizer(pathArg, "/");
+ while (st.hasMoreTokens())
+ {
+ String childName = st.nextToken();
+ node = nodeService.getChildByName(node, ContentModel.ASSOC_CONTAINS, childName);
+ if (node == null)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid 'path' variable");
+ }
+ }
+ }
+
+ return node;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Generates an activity entry for the link
+ */
+
+ protected void addActivityEntry(String activityType, String title, String nodeRef, String site)
+ {
+ try
+ {
+ StringWriter activityJson = new StringWriter();
+ JSONWriter activity = new JSONWriter(activityJson);
+ activity.startObject();
+ activity.writeValue("title", title);
+ activity.writeValue("nodeRef", nodeRef);
+ activity.writeValue("page", "document-details?nodeRef=" + nodeRef);
+ activity.endObject();
+
+ activityService.postActivity(
+ activityType,
+ site,
+ ACTIVITY_TOOL,
+ activityJson.toString());
+ }
+ catch (Exception e)
+ {
+ // Warn, but carry on
+ logger.warn("Error adding link event to activities feed", e);
+ }
+ }
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ public void setSiteService(SiteService siteService)
+ {
+ this.siteService = siteService;
+ }
+
+ public void setDocumentLinkService(DocumentLinkService documentLinkService)
+ {
+ this.documentLinkService = documentLinkService;
+ }
+
+ public void setActivityService(ActivityService activityService)
+ {
+ this.activityService = activityService;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/doclink/DocLinkPost.java b/source/java/org/alfresco/repo/web/scripts/doclink/DocLinkPost.java
index d0feef5c06..4557f89469 100644
--- a/source/java/org/alfresco/repo/web/scripts/doclink/DocLinkPost.java
+++ b/source/java/org/alfresco/repo/web/scripts/doclink/DocLinkPost.java
@@ -23,95 +23,177 @@
* along with Alfresco. If not, see .
* #L%
*/
-package org.alfresco.repo.web.scripts.doclink;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.repo.security.permissions.AccessDeniedException;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.util.ParameterCheck;
-import org.json.simple.JSONObject;
-import org.json.simple.JSONValue;
-import org.json.simple.parser.ParseException;
-import org.springframework.extensions.webscripts.Cache;
-import org.springframework.extensions.webscripts.Status;
-import org.springframework.extensions.webscripts.WebScriptException;
-import org.springframework.extensions.webscripts.WebScriptRequest;
-
-/**
- * This class is the controller for the doclink.post webscript doclink.post is a
- * webscript for creating a link of a document within a target destination
- *
- * @author Ana Bozianu
- * @since 5.1
- */
-public class DocLinkPost extends AbstractDocLink
-{
- private static String PARAM_DESTINATION_NODE = "destinationNodeRef";
-
- @Override
- protected Map executeImpl(WebScriptRequest req, Status status, Cache cache)
- {
- NodeRef sourceNodeRef = null;
- NodeRef destinationNodeRef = null;
-
- /* Parse the template vars */
- Map templateVars = req.getServiceMatch().getTemplateVars();
- sourceNodeRef = parseNodeRefFromTemplateArgs(templateVars);
-
- /* Parse the JSON content */
- JSONObject json = null;
- String contentType = req.getContentType();
- if (contentType != null && contentType.indexOf(';') != -1)
- {
- contentType = contentType.substring(0, contentType.indexOf(';'));
- }
- if (MimetypeMap.MIMETYPE_JSON.equals(contentType))
- {
- try
- {
- json = (JSONObject) JSONValue.parseWithException(req.getContent().getContent());
- }
- catch (IOException io)
- {
- throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + io.getMessage());
- }
- catch (ParseException pe)
- {
- throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + pe.getMessage());
- }
- }
- else
- {
- throw new WebScriptException(Status.STATUS_BAD_REQUEST, "invalid request content type");
- }
-
- /* Parse the destination NodeRef parameter */
- String destinationNodeParam = (String) json.get(PARAM_DESTINATION_NODE);
- ParameterCheck.mandatoryString("destinationNodeParam", destinationNodeParam);
- destinationNodeRef = new NodeRef(destinationNodeParam);
-
- /* Create link */
- NodeRef linkNodeRef = null;
- try
- {
- linkNodeRef = documentLinkService.createDocumentLink(sourceNodeRef, destinationNodeRef);
- }
- catch (IllegalArgumentException ex)
- {
- throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid Arguments: " + ex.getMessage());
- }
- catch (AccessDeniedException e)
- {
- throw new WebScriptException(Status.STATUS_FORBIDDEN, "You don't have permission to perform this operation");
- }
-
- /* Build response */
- Map model = new HashMap();
- model.put("linkNodeRef", linkNodeRef.toString());
- return model;
- }
-}
+package org.alfresco.repo.web.scripts.doclink;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.activities.ActivityType;
+import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.repo.security.permissions.AccessDeniedException;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.util.ParameterCheck;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.json.simple.parser.ParseException;
+import org.springframework.extensions.webscripts.Cache;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.WebScriptException;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+
+/**
+ * This class is the controller for the doclink.post webscript doclink.post is a
+ * webscript for creating a link of a document within a target destination
+ *
+ * @author Ana Bozianu
+ * @since 5.1
+ */
+public class DocLinkPost extends AbstractDocLink
+{
+ private static final String PARAM_DESTINATION_NODE = "destinationNodeRef";
+ private static final String PARAM_MULTIPLE_FILES = "multipleFiles";
+
+ @Override
+ protected Map executeImpl(WebScriptRequest req, Status status, Cache cache)
+ {
+ NodeRef sourceNodeRef = null;
+ NodeRef destinationNodeRef = null;
+
+ /* Parse the template vars */
+ Map templateVars = req.getServiceMatch().getTemplateVars();
+ sourceNodeRef = parseNodeRefFromTemplateArgs(templateVars);
+
+ /* Parse the JSON content */
+ JSONObject json = null;
+ String contentType = req.getContentType();
+ if (contentType != null && contentType.indexOf(';') != -1)
+ {
+ contentType = contentType.substring(0, contentType.indexOf(';'));
+ }
+ if (MimetypeMap.MIMETYPE_JSON.equals(contentType))
+ {
+ try
+ {
+ json = (JSONObject) JSONValue.parseWithException(req.getContent().getContent());
+ }
+ catch (IOException io)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + io.getMessage());
+ }
+ catch (ParseException pe)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + pe.getMessage());
+ }
+ }
+ else
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST, "invalid request content type");
+ }
+
+ /* Parse the destination NodeRef parameter */
+ String destinationNodeParam = (String) json.get(PARAM_DESTINATION_NODE);
+ ParameterCheck.mandatoryString("destinationNodeParam", destinationNodeParam);
+ destinationNodeRef = new NodeRef(destinationNodeParam);
+
+ List nodeRefs = new ArrayList();
+ if (json.containsKey(PARAM_MULTIPLE_FILES))
+ {
+ JSONArray multipleFiles = (JSONArray) json.get(PARAM_MULTIPLE_FILES);
+ for (int i = 0; i < multipleFiles.size(); i++)
+ {
+ String nodeRefString = (String) multipleFiles.get(i);
+ if (nodeRefString != null)
+ {
+ try
+ {
+ NodeRef nodeRefToCreateLink = new NodeRef(nodeRefString);
+ nodeRefs.add(nodeRefToCreateLink);
+ }
+ catch (AlfrescoRuntimeException ex)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid Arguments: " + ex.getMessage());
+ }
+
+ }
+ }
+ }
+ else
+ {
+ nodeRefs.add(sourceNodeRef);
+ }
+
+ // getSite for destination folder
+ String siteName = siteService.getSiteShortName(destinationNodeRef);
+
+ ArrayList