package org.exoplatform.ecms.upgrade.sanitization; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.Session; import javax.jcr.query.Query; import javax.jcr.query.QueryResult; import org.apache.commons.lang.StringUtils; import org.exoplatform.commons.upgrade.UpgradeProductPlugin; import org.exoplatform.commons.version.util.VersionComparator; import org.exoplatform.container.xml.InitParams; import org.exoplatform.services.ecm.publication.PublicationService; import org.exoplatform.services.jcr.RepositoryService; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.wcm.publication.PublicationDefaultStates; import org.exoplatform.services.wcm.utils.WCMCoreUtils; public class InternalLinksUpgradePlugin extends UpgradeProductPlugin { private RepositoryService repoService_; private static final Log LOG = ExoLogger.getLogger(InternalLinksUpgradePlugin.class.getName()); public InternalLinksUpgradePlugin(RepositoryService repoService, InitParams initParams){ super(initParams); repoService_ = repoService; } @Override public void processUpgrade(String oldVersion, String newVersion) { /** * Migrate binary data jcr:data which still contains "/sites content/live" in its values */ migrateJCRDataContents(); } @Override public boolean shouldProceedToUpgrade(String newVersion, String previousVersion) { //return true anly for the first version of platform return VersionComparator.isAfter(newVersion,previousVersion); } /** * Migrate binnary data jcr:data which still contains "/sites content/live" in its values */ private void migrateJCRDataContents() { try { Session session = WCMCoreUtils.getSystemSessionProvider().getSession("collaboration",repoService_.getCurrentRepository()); if (LOG.isInfoEnabled()) { LOG.info("=====Start migrate old links from jcr data===="); } List<String> documentMixinTypes = new ArrayList<String>(); Set<String> nodesToRepublish = new HashSet<String>(); // for performance reason we limit search to js,html and csscontents documentMixinTypes.add("exo:jsFile"); documentMixinTypes.add("exo:htmlFile"); documentMixinTypes.add("exo:cssFile"); documentMixinTypes.add("exo:webContent"); for (String type : documentMixinTypes) { StringBuilder statement = new StringBuilder().append("select * from ").append(type).append(" ORDER BY exo:name DESC "); QueryResult result = session.getWorkspace().getQueryManager().createQuery(statement.toString(), Query.SQL).execute(); NodeIterator nodeIter = result.getNodes(); while (nodeIter.hasNext()) { try { Node node = nodeIter.nextNode(); if (type.equals("exo:webContent")) { if (node.hasProperty("exo:summary")) { String summary = node.getProperty("exo:summary").getString(); if (summary.contains("/sites content/live/") || summary.contains("/sites%20content/live/")) { LOG.info("=====Migrating data summary '" + node.getPath() + "' ====="); String newData = StringUtils.replaceEachRepeatedly(summary, new String[]{"/sites content/live/", "/sites%20content/live/"}, new String[]{"/sites/", "/sites/"}); node.setProperty("exo:summary", newData); session.save(); nodesToRepublish.add(node.getPath()); } } } else { if (node.hasNode("jcr:content")) { Node content = node.getNode("jcr:content"); if (content.hasProperty("jcr:mimeType")) { String mimeType = content.getProperty("jcr:mimeType").getString(); if (mimeType.startsWith("text") || mimeType.contains("javascript")) { String jcrData = content.getProperty("jcr:data").getString(); if (jcrData.contains("/sites content/live/") || jcrData.contains("/sites%20content/live/")) { LOG.info("=====Migrating data contents '" + content.getParent().getPath() + "' ====="); String newData = StringUtils.replaceEachRepeatedly(jcrData, new String[]{"/sites content/live/", "/sites%20content/live/"}, new String[]{"/sites/", "/sites/"}); content.setProperty("jcr:data", newData); session.save(); Node parent = node.getParent(); if (parent.isNodeType("exo:webContent")) { nodesToRepublish.add(parent.getPath()); continue; } //for subnodes in some folders like css, js, documents, medias if (parent.getPath().equals("/")) { nodesToRepublish.add(node.getPath()); continue; } Node grandParent = parent.getParent(); if (grandParent.isNodeType("exo:webContent")) { nodesToRepublish.add(grandParent.getPath()); continue; } //for subnodes in some folders like images, videos, audio if (grandParent.getPath().equals("/")) { nodesToRepublish.add(node.getPath()); continue; } Node ancestor = grandParent.getParent(); if (ancestor.isNodeType("exo:webContent")) { nodesToRepublish.add(ancestor.getPath()); continue; } nodesToRepublish.add(node.getPath()); } } } } } } catch (Exception e) { LOG.error("An unexpected error occurs when migrating JCR Data Content: ",e); } } } for (String nodePath : nodesToRepublish) { try { republishNode((Node)session.getItem(nodePath)); } catch (Exception e) { LOG.error("An unexpected error occurs when republishing content: ",e); } } if (LOG.isInfoEnabled()) { LOG.info("===== Migrate data in contents completed ====="); } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("An unexpected error occurs when migrating JCR Data Contents: ",e); } } } /* Republish node */ private void republishNode(Node checkedNode) throws Exception { PublicationService publicationService = (PublicationService)WCMCoreUtils.getService(PublicationService.class); if (publicationService.isNodeEnrolledInLifecycle(checkedNode) && PublicationDefaultStates.PUBLISHED.equalsIgnoreCase(publicationService.getCurrentState(checkedNode))){ HashMap<String, String> context = new HashMap<String, String>(); LOG.info("=====Republish '"+ checkedNode.getPath()+ "' ====="); publicationService.changeState(checkedNode,PublicationDefaultStates.DRAFT,context); publicationService.changeState(checkedNode,PublicationDefaultStates.PUBLISHED,context); } } }