From 337e05565dcb8e1351f5a9546136673b8bdc4800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Merino=20Echeverr=C3=ADa?= Date: Wed, 1 Jun 2016 16:15:20 +0200 Subject: [PATCH] SAK-31123 - Web Service for copy content updated with Entity Transferrer. (#2584) --- .../sakaiproject/webservices/SakaiScript.java | 297 ++++++++++++++---- 1 file changed, 243 insertions(+), 54 deletions(-) diff --git a/webservices/cxf/src/java/org/sakaiproject/webservices/SakaiScript.java b/webservices/cxf/src/java/org/sakaiproject/webservices/SakaiScript.java index 27a2fb922fc6..9611b87f450e 100644 --- a/webservices/cxf/src/java/org/sakaiproject/webservices/SakaiScript.java +++ b/webservices/cxf/src/java/org/sakaiproject/webservices/SakaiScript.java @@ -27,6 +27,8 @@ import java.util.Set; import java.util.Date; import java.util.Collections; +import java.util.Collection; +import java.util.Map.Entry; import javax.jws.WebMethod; import javax.jws.WebParam; @@ -54,11 +56,13 @@ import org.sakaiproject.calendar.api.CalendarEventEdit; import org.sakaiproject.entity.api.EntityProducer; import org.sakaiproject.entity.api.EntityTransferrer; +import org.sakaiproject.entity.api.EntityTransferrerRefMigrator; import org.sakaiproject.entity.api.ResourceProperties; import org.sakaiproject.entity.api.ResourcePropertiesEdit; import org.sakaiproject.event.api.UsageSession; import org.sakaiproject.event.api.UsageSessionService; import org.sakaiproject.exception.IdUnusedException; +import org.sakaiproject.exception.PermissionException; import org.sakaiproject.site.api.Group; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.api.SitePage; @@ -76,6 +80,7 @@ import org.sakaiproject.util.ResourceLoader; import org.sakaiproject.util.BaseResourcePropertiesEdit; import org.sakaiproject.util.Xml; +import org.sakaiproject.util.Web; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -4142,8 +4147,8 @@ public String copySiteContent( // If not admin, check maintainer membership in the source site if (!isSuperUser && !securityService.unlock(SiteService.SECURE_UPDATE_SITE, site.getReference())) { - LOG.warn("WS copyResources(): Permission denied. Must be super user to copy a site in which you are not a maintainer."); - throw new RuntimeException("WS copyResources(): Permission denied. Must be super user to copy a site in which you are not a maintainer."); + LOG.warn("WS copySiteContent(): Permission denied. Must be super user to copy a site in which you are not a maintainer."); + throw new RuntimeException("WS copySiteContent(): Permission denied. Must be super user to copy a site in which you are not a maintainer."); } List pages = site.getPages(); @@ -4176,12 +4181,26 @@ public String copySiteContent( } } - for (String toolId : toolIds) { - //transfer content - transferCopyEntities( - toolId, - contentHostingService.getSiteCollection(sourcesiteid), - contentHostingService.getSiteCollection(destinationsiteid)); + for (String toolId : toolIds) + { + Map entityMap; + Map transversalMap = new HashMap(); + + if (!toolId.equalsIgnoreCase("sakai.resources")) + { + entityMap = transferCopyEntities(toolId, sourcesiteid, destinationsiteid); + } + else + { + entityMap = transferCopyEntities(toolId, contentHostingService.getSiteCollection(sourcesiteid), contentHostingService.getSiteCollection(destinationsiteid)); + } + + if(entityMap != null) + { + transversalMap.putAll(entityMap); + } + + updateEntityReferences(toolId, sourcesiteid, transversalMap, site); } } catch (Exception e) { LOG.error("WS copySiteContent(): " + e.getClass().getName() + " : " + e.getMessage(), e); @@ -4204,37 +4223,53 @@ public String copySiteContent( @Produces("text/plain") @GET public String copySiteContentForTool( - @WebParam(name = "sessionid", partName = "sessionid") @QueryParam("sessionid") String sessionid, - @WebParam(name = "sourcesiteid", partName = "sourcesiteid") @QueryParam("sourcesiteid") String sourcesiteid, - @WebParam(name = "destinationsiteid", partName = "destinationsiteid") @QueryParam("destinationsiteid") String destinationsiteid, - @WebParam(name = "toolid", partName = "toolid") @QueryParam("toolid") String toolid) { - - Session session = establishSession(sessionid); - - try { - //check if both sites exist - Site site = siteService.getSite(sourcesiteid); - site = siteService.getSite(destinationsiteid); - - // If not admin, check maintainer membership in the source site - if (!securityService.isSuperUser(session.getUserId()) && !securityService.unlock(SiteService.SECURE_UPDATE_SITE, site.getReference())) { - LOG.warn("WS copyResources(): Permission denied. Must be super user to copy a site in which you are not a maintainer."); - throw new RuntimeException("WS copyResources(): Permission denied. Must be super user to copy a site in which you are not a maintainer."); - } - - //transfer content - transferCopyEntities( - toolid, - contentHostingService.getSiteCollection(sourcesiteid), - contentHostingService.getSiteCollection(destinationsiteid)); - } catch (Exception e) { - LOG.error("WS copySiteContentForTool(): " + e.getClass().getName() + " : " + e.getMessage(), e); - return e.getClass().getName() + " : " + e.getMessage(); - } - return "success"; + @WebParam(name = "sessionid", partName = "sessionid") @QueryParam("sessionid") String sessionid, + @WebParam(name = "sourcesiteid", partName = "sourcesiteid") @QueryParam("sourcesiteid") String sourcesiteid, + @WebParam(name = "destinationsiteid", partName = "destinationsiteid") @QueryParam("destinationsiteid") String destinationsiteid, + @WebParam(name = "toolid", partName = "toolid") @QueryParam("toolid") String toolid) + { + Session session = establishSession(sessionid); + Set toolsCopied = new HashSet(); + Map transversalMap = new HashMap(); + + try + { + //check if both sites exist + Site site = siteService.getSite(sourcesiteid); + site = siteService.getSite(destinationsiteid); + + // If not admin, check maintainer membership in the source site + if (!securityService.isSuperUser(session.getUserId()) && !securityService.unlock(SiteService.SECURE_UPDATE_SITE, site.getReference())) + { + LOG.warn("WS copySiteContentForTool(): Permission denied. Must be super user to copy a site in which you are not a maintainer."); + throw new RuntimeException("WS copySiteContentForTool(): Permission denied. Must be super user to copy a site in which you are not a maintainer."); + } + + Map entityMap; + if (!toolid.equalsIgnoreCase("sakai.resources")) + { + entityMap = transferCopyEntities(toolid, sourcesiteid, destinationsiteid); + } + else + { + entityMap = transferCopyEntities(toolid, contentHostingService.getSiteCollection(sourcesiteid), contentHostingService.getSiteCollection(destinationsiteid)); + } + + if(entityMap != null) + { + transversalMap.putAll(entityMap); + } + + updateEntityReferences(toolid, sourcesiteid, transversalMap, site); + } + catch (Exception e) + { + LOG.error("WS copySiteContentForTool(): " + e.getClass().getName() + " : " + e.getMessage(), e); + return e.getClass().getName() + " : " + e.getMessage(); + } + return "success"; } - /** * Transfer a copy of all entites from another context for any entity * producer that claims this tool id. @@ -4243,25 +4278,179 @@ public String copySiteContentForTool( * @param fromContext The context to import from. * @param toContext The context to import into. */ - private void transferCopyEntities(String toolId, String fromContext, String toContext) { - // offer to all EntityProducers - for (Iterator i = entityManager.getEntityProducers().iterator(); i.hasNext(); ) { - EntityProducer ep = (EntityProducer) i.next(); - if (ep instanceof EntityTransferrer) { - try { - EntityTransferrer et = (EntityTransferrer) ep; - - // if this producer claims this tool id - if (ArrayUtil.contains(et.myToolIds(), toolId)) { - et.transferCopyEntities(fromContext, toContext, new ArrayList()); - } - } catch (Throwable t) { - LOG.warn(this + ".transferCopyEntities: Error encountered while asking EntityTransfer to transferCopyEntities from: " + fromContext + " to: " + toContext, t); - } - } - } + protected Map transferCopyEntities(String toolId, String fromContext, String toContext) + { + Map transversalMap = new HashMap(); + + // offer to all EntityProducers + for (Iterator i = entityManager.getEntityProducers().iterator(); i.hasNext();) + { + EntityProducer ep = (EntityProducer) i.next(); + if (ep instanceof EntityTransferrer) + { + try + { + EntityTransferrer et = (EntityTransferrer) ep; + + // if this producer claims this tool id + if (ArrayUtil.contains(et.myToolIds(), toolId)) + { + if(ep instanceof EntityTransferrerRefMigrator) + { + EntityTransferrerRefMigrator etMp = (EntityTransferrerRefMigrator) ep; + Map entityMap = etMp.transferCopyEntitiesRefMigrator(fromContext, toContext, new ArrayList(), true); + if(entityMap != null) + { + transversalMap.putAll(entityMap); + } + } + else + { + et.transferCopyEntities(fromContext, toContext, new ArrayList(), true); + } + } + } + catch (Throwable t) + { + LOG.warn("Error encountered while asking EntityTransfer to transferCopyEntities from: " + fromContext + " to: " + toContext, t); + } + } + } + + // record direct URL for this tool in old and new sites, so anyone using the URL in HTML text will + // get a proper update for the HTML in the new site + // Some tools can have more than one instance. Because getTools should always return tools + // in order, we can assume that if there's more than one instance of a tool, the instances + // correspond + + Site fromSite = null; + Site toSite = null; + Collection fromTools = null; + Collection toTools = null; + try + { + fromSite = siteService.getSite(fromContext); + toSite = siteService.getSite(toContext); + fromTools = fromSite.getTools(toolId); + toTools = toSite.getTools(toolId); + } + catch (Exception e) + { + LOG.warn("transferCopyEntities: can't get site:" + e.getMessage()); + } + + // getTools appears to return tools in order. So we should be able to match them + if (fromTools != null && toTools != null) + { + Iterator toToolIt = toTools.iterator(); + for (ToolConfiguration fromTool: fromTools) + { + if (toToolIt.hasNext()) + { + ToolConfiguration toTool = toToolIt.next(); + String fromUrl = serverConfigurationService.getPortalUrl() + "/directtool/" + Web.escapeUrl(fromTool.getId()) + "/"; + String toUrl = serverConfigurationService.getPortalUrl() + "/directtool/" + Web.escapeUrl(toTool.getId()) + "/"; + if (transversalMap.get(fromUrl) == null) + { + transversalMap.put(fromUrl, toUrl); + } + if (shortenedUrlService.shouldCopy(fromUrl)) + { + fromUrl = shortenedUrlService.shorten(fromUrl, false); + toUrl = shortenedUrlService.shorten(toUrl, false); + if (fromUrl != null && toUrl != null) + { + transversalMap.put(fromUrl, toUrl); + } + } + } + else + { + break; + } + } + } + + return transversalMap; } + + protected void updateEntityReferences(String toolId, String toContext, Map transversalMap, Site newSite) + { + if (toolId.equalsIgnoreCase("sakai.iframe.site")) + { + updateSiteInfoToolEntityReferences(transversalMap, newSite); + } + else + { + for (Iterator i = entityManager.getEntityProducers().iterator(); i.hasNext();) + { + EntityProducer ep = (EntityProducer) i.next(); + if (ep instanceof EntityTransferrerRefMigrator && ep instanceof EntityTransferrer) + { + try + { + EntityTransferrer et = (EntityTransferrer) ep; + EntityTransferrerRefMigrator etRM = (EntityTransferrerRefMigrator) ep; + + // if this producer claims this tool id + if (ArrayUtil.contains(et.myToolIds(), toolId)) + { + etRM.updateEntityReferences(toContext, transversalMap); + } + } + catch (Throwable t) + { + LOG.error("Error encountered while asking EntityTransfer to updateEntityReferences at site: " + toContext, t); + } + } + } + } + } + + private void updateSiteInfoToolEntityReferences(Map transversalMap, Site newSite) + { + if(transversalMap != null && transversalMap.size() > 0 && newSite != null) + { + Set> entrySet = (Set>) transversalMap.entrySet(); + + String msgBody = newSite.getDescription(); + if(msgBody != null && !"".equals(msgBody)) + { + boolean updated = false; + Iterator> entryItr = entrySet.iterator(); + while(entryItr.hasNext()) + { + Entry entry = (Entry) entryItr.next(); + String fromContextRef = entry.getKey(); + if(msgBody.contains(fromContextRef)) + { + msgBody = msgBody.replace(fromContextRef, entry.getValue()); + updated = true; + } + } + if(updated) + { + //update the site b/c some tools (Lessonbuilder) updates the site structure (add/remove pages) and we don't want to + //over write this + try + { + newSite = siteService.getSite(newSite.getId()); + newSite.setDescription(msgBody); + siteService.save(newSite); + } + catch (IdUnusedException e) { + // TODO: + } + catch (PermissionException p) + { + // TODO: + } + } + } + } + } + /** * Get any subsites for a given site *