/*************************************************************************** * Copyright (C) 2003-2009 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * 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, see<http://www.gnu.org/licenses/>. * **************************************************************************/ package org.exoplatform.ecms.upgrade.sanitization; 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.cms.BasePath; import org.exoplatform.services.cms.impl.DMSConfiguration; import org.exoplatform.services.cms.views.ManageViewService; import org.exoplatform.services.jcr.RepositoryService; import org.exoplatform.services.jcr.ext.common.SessionProvider; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.wcm.utils.WCMCoreUtils; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.Session; import javax.jcr.Value; import javax.jcr.query.Query; import javax.jcr.query.QueryResult; import java.util.ArrayList; import java.util.List; /** * This upgrade plugin will be used to migrate all the old data to the new one which related to * the changing of Sanitization in PLF4 */ public class SanitizationUpgradePlugin extends UpgradeProductPlugin { private DMSConfiguration dmsConfiguration_; private RepositoryService repoService_; private ManageViewService viewService_; private static final Log LOG = ExoLogger.getLogger(SanitizationUpgradePlugin.class.getName()); public SanitizationUpgradePlugin(RepositoryService repoService, DMSConfiguration dmsConfiguration, ManageViewService viewService, InitParams initParams) { super(initParams); repoService_ = repoService; dmsConfiguration_ = dmsConfiguration; viewService_ = viewService; } @Override public void processUpgrade(String oldVersion, String newVersion) { if (LOG.isInfoEnabled()) { LOG.info("Start " + this.getClass().getName() + "............."); } /* Migrate data for all user views */ migrateViews(); /* Migrate data for view templates */ migrateViewTemplates(); /* Migrate data for all drives */ migrateDrives(); /** * Migrate portlet preferences which contains the "/sites content/live" path to "/sites" */ migratePortletPreferences(); /** * Migrate exo:links which still contains "/sites content/live" in its properties */ migrateLinkInContents(); /** * Migrate activities which contains "/sites content/live" in the url */ migrateSocialActivities(); /** * Migrate taxonomy actions which contains some properties which still point to old path related to "/sites content/live" */ migrateTaxonomyAction(); /** * Migrate preference 'Drive name' of site explorer portlet which should be changed to Collaboration instead of collaboration" */ migrateDriveNameOfPortletPreferences(); } @Override public boolean shouldProceedToUpgrade(String newVersion, String previousVersion) { //return true anly for the first version of platform return VersionComparator.isAfter(newVersion,previousVersion); } /* Migrate data for all user views */ private void migrateViews() { SessionProvider sessionProvider = null; try { sessionProvider = SessionProvider.createSystemProvider(); Session session = sessionProvider.getSession(dmsConfiguration_.getConfig().getSystemWorkspace(), repoService_.getCurrentRepository()); String[] oldViewTemplates = {"ListView", "ContentView", "ThumbnailsView", "IconView", "TimelineView", "CoverFlow", "SystemView", "SlideShowView"}; if (LOG.isInfoEnabled()) { LOG.info("=====Start migrate data for all user views====="); } Node views = (Node)session.getItem("/exo:ecm/views/userviews"); NodeIterator nodeIter = views.getNodes(); while(nodeIter.hasNext()) { Node viewNode = nodeIter.nextNode(); String template = viewNode.getProperty("exo:template").getString(); String templateName = StringUtils.substringAfterLast(template, "/"); for(String oldTemp : oldViewTemplates) { if(templateName.equals(oldTemp)) { if(isContainOldView(viewNode.getName())) { if (LOG.isInfoEnabled()) { LOG.info("=====Removing view '"+viewNode.getName()+"'====="); } viewNode.remove(); } else { String newTemplate = "List"; if(templateName.equals("ListView")) newTemplate = template.replace(templateName, "List"); else if(templateName.equals("ContentView")) newTemplate = template.replace(templateName, "Content"); else if(templateName.equals("ThumbnailsView")) newTemplate = template.replace(templateName, "Thumbnails"); else if(templateName.equals("IconView")) newTemplate = template.replace(templateName, "Thumbnails"); else if(templateName.equals("TimelineView")) newTemplate = template.replace(templateName, "List"); else if(templateName.equals("CoverFlow")) newTemplate = template.replace(templateName, "Thumbnails"); else if(templateName.equals("SystemView")) newTemplate = template.replace(templateName, "List"); else if(templateName.equals("SlideShowView")) newTemplate = template.replace(templateName, "Thumbnails"); if (LOG.isInfoEnabled()) { LOG.info("=====Modifying view '"+viewNode.getName()+"'====="); } viewNode.setProperty("exo:template", newTemplate); } } } } session.save(); if (LOG.isInfoEnabled()) { LOG.info("=====Completed the migration data for user views====="); } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("An unexpected error occurs when migrate views", e); } } finally { if (sessionProvider != null) { sessionProvider.close(); } } } private boolean isContainOldView(String viewName) { String[] oldViewNames = {"timeline-view", "list-view", "icon-view", "admin-view", "simple-view", "slide-show", "cover-flow", "anonymous-view", "taxonomy-list", "taxonomy-icons", "system-view", "wcm-view", "authoring-view", "wcm-category-view"}; for(String vName : oldViewNames) { if(viewName.contains(vName)) return true; } return false; } /* Migrate data for view templates */ private void migrateViewTemplates() { SessionProvider sessionProvider = null; try { if (LOG.isInfoEnabled()) { LOG.info("=====Start migrate data for all user views template====="); } sessionProvider = SessionProvider.createSystemProvider(); Session session = sessionProvider.getSession(dmsConfiguration_.getConfig().getSystemWorkspace(), repoService_.getCurrentRepository()); String[] oldViewTemplates = {"ListView", "ContentView", "ThumbnailsView", "IconView", "TimelineView", "CoverFlow", "SystemView", "SlideShowView"}; List<Node> templates = viewService_.getAllTemplates(BasePath.ECM_EXPLORER_TEMPLATES, sessionProvider); for(Node template : templates) { for(String oldViewTemp : oldViewTemplates) { if(template.getName().equals(oldViewTemp)) { LOG.info(" * Removing the old view template " +template.getName()+ ""); template.remove(); break; } } } session.save(); if (LOG.isInfoEnabled()) { LOG.info("=====Completed the migration data for user views template====="); } } catch(Exception e) { if (LOG.isErrorEnabled()) { LOG.error("An unexpected error occurs when migrate view templates", e); } } finally { if (sessionProvider != null) { sessionProvider.close(); } } } /* Migrate data for all drives */ private void migrateDrives() { if (LOG.isInfoEnabled()) { LOG.info("=====Start migrate data for drives====="); } SessionProvider sessionProvider = null; try { sessionProvider = SessionProvider.createSystemProvider(); Session session = sessionProvider.getSession(dmsConfiguration_.getConfig().getSystemWorkspace(), repoService_.getCurrentRepository()); Node drives = (Node)session.getItem("/exo:ecm/exo:drives"); NodeIterator nodeIter = drives.getNodes(); while(nodeIter.hasNext()) { Node drive = nodeIter.nextNode(); if (LOG.isInfoEnabled()) { LOG.info(" * Migrating the drive " +drive.getName()+ ""); } String path = drive.getProperty("exo:path").getString(); if(path.startsWith("/sites content/live")) { drive.setProperty("exo:path", path.replace("/sites content/live", "/sites")); drive.setProperty("exo:views", "Web"); } else if(path.equals("/Groups${groupId}")) { path = path.replace("/Groups${groupId}", "/Groups${groupId}/Documents"); drive.setProperty("exo:path", path); drive.setProperty("exo:views", "List, Icons"); } else if(drive.getName().equals("collaboration") && path.equals("/")) { drive.remove(); } else if(drive.getName().equals("Trash") && path.equals("/Trash")) { drive.setProperty("exo:views", "Admin"); } else if(drive.getName().equals("acme-category")) { drive.remove(); } else if(drive.getName().equals("Private") || (drive.getName().equals("Public"))) { drive.remove(); } else if("Personal Documents".equals(drive.getName())) { drive.setProperty("exo:viewNonDocument", false); } else if(drive.getProperty("exo:workspace").getString().equals("dms-system") && path.equals("/")) { drive.remove(); } else { String views = drive.getProperty("exo:views").getString(); String[] arrView; if(views.contains(",")) { arrView = views.split(","); } else { arrView = new String[] {views}; } StringBuilder strViews = new StringBuilder(); for(String view : arrView) { if(strViews.length() > 0) strViews.append(", "); view = view.trim(); if(view.contains("timeline-view")) { strViews.append("List"); } else if(view.contains("list-view")) { strViews.append("List"); } else if(view.contains("icon-view")) { strViews.append("Icons"); } else if(view.contains("cover-flow")) { strViews.append("Icons"); } else if(view.contains("admin-view")) { strViews.append("Admin"); } else if(view.contains("simple-view")) { strViews.append("Icons"); } else if(view.contains("slide-show")) { strViews.append("Icons"); } else if(view.contains("anonymous-view")) { strViews.append("Icons"); } else if(view.contains("taxonomy-list")) { strViews.append("Categories"); } else if(view.contains("taxonomy-icons")) { strViews.append("Categories"); } else if(view.contains("system-view")) { strViews.append("List"); } else if(view.contains("wcm-view")) { strViews.append("Web"); } else if(view.contains("authoring-view")) { strViews.append("Web"); } else if(view.contains("wcm-category-view")) { strViews.append("Categories"); } else { strViews.append(view); } } drive.setProperty("exo:views", strViews.toString()); } } session.save(); if (LOG.isInfoEnabled()) { LOG.info("=====Completed the migration data for drives====="); } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("An unexpected error occurs when migrate drives", e); } } finally { if (sessionProvider != null) { sessionProvider.close(); } } } /** * Migrate portlet preferences which contains the "/sites content/live" path to "/sites" */ private void migratePortletPreferences() { SessionProvider sessionProvider = null; try { sessionProvider = SessionProvider.createSystemProvider(); Session session = sessionProvider.getSession("portal-system", repoService_.getCurrentRepository()); if (LOG.isInfoEnabled()) { LOG.info("=====Start migrate old preferences====="); } String statement = "select * from mop:portletpreference where mop:value like '%/sites content/live/%'"; QueryResult result = session.getWorkspace().getQueryManager().createQuery(statement, Query.SQL).execute(); NodeIterator nodeIter = result.getNodes(); while(nodeIter.hasNext()) { Node preferenceNode = nodeIter.nextNode(); String oldPath =preferenceNode.getProperty("mop:value").getValues()[0].getString(); String newPath= StringUtils.replace(oldPath, "/sites content/live/", "/sites/"); preferenceNode.setProperty("mop:value", new String[]{newPath}); } session.save(); if (LOG.isInfoEnabled()) { LOG.info("===== Portlet preference upgrade completed ====="); } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("An unexpected error occurs when migrating old preferences: ", e); } } finally { if (sessionProvider != null) { sessionProvider.close(); } } } /** * Migrate exo:links which still contains "/sites content/live" in its properties */ private void migrateLinkInContents() { SessionProvider sessionProvider = null; try { sessionProvider = SessionProvider.createSystemProvider(); Session session = sessionProvider.getSession("collaboration", repoService_.getCurrentRepository()); if (LOG.isInfoEnabled()) { LOG.info("=====Start migrate old link in contents====="); } String statement = "select * from exo:linkable where exo:links like '%/sites content/live/%'"; QueryResult result = session.getWorkspace().getQueryManager().createQuery(statement, Query.SQL).execute(); NodeIterator nodeIter = result.getNodes(); while(nodeIter.hasNext()) { Node contentNode = nodeIter.nextNode(); if (LOG.isInfoEnabled()) { LOG.info("=====Migrating content '"+contentNode.getPath()+"' ====="); } Value[] oldLinks = contentNode.getProperty("exo:links").getValues(); List<String> newLinks = new ArrayList<String>(); for(Value linkValue : oldLinks) { newLinks.add(StringUtils.replace(linkValue.getString(), "/sites content/live/", "/sites/")); } contentNode.setProperty("exo:links", newLinks.toArray(new String[newLinks.size()])); } session.save(); if (LOG.isInfoEnabled()) { LOG.info("===== Migrate content links completed ====="); } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("An unexpected error occurs when migrating content links: ", e); } } finally { if (sessionProvider != null) { sessionProvider.close(); } } } /** * Migrate activities which contains "/sites content/live" in the url */ private void migrateSocialActivities() { SessionProvider sessionProvider = null; try { sessionProvider = SessionProvider.createSystemProvider(); Session session = sessionProvider.getSession("social", repoService_.getCurrentRepository()); if (LOG.isInfoEnabled()) { LOG.info("=====Start migrate soc:url for all activities====="); } String statement = "SELECT * FROM soc:activity WHERE soc:url like '%/sites content/live/%'"; QueryResult result = session.getWorkspace().getQueryManager().createQuery(statement, Query.SQL).execute(); NodeIterator nodeIter = result.getNodes(); while(nodeIter.hasNext()) { Node activity = nodeIter.nextNode(); String nodeUrl = activity.getProperty("soc:url").getString(); activity.setProperty("soc:url", StringUtils.replace(nodeUrl, "/sites content/live/", "/sites/")); } session.save(); if (LOG.isInfoEnabled()) { LOG.info("=====Completed the migration for soc:url====="); } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("An unexpected error occurs when migrating activities: ", e); } } finally { if (sessionProvider != null) { sessionProvider.close(); } } } /** * Migrate taxonomy actions which contains some properties which still point to old path related to "/sites content/live" */ private void migrateTaxonomyAction() { SessionProvider sessionProvider = null; try { sessionProvider = SessionProvider.createSystemProvider(); String wsName = repoService_.getCurrentRepository().getConfiguration().getDefaultWorkspaceName(); Session session = sessionProvider.getSession(wsName, repoService_.getCurrentRepository()); if (LOG.isInfoEnabled()) { LOG.info("=====Start to migrate taxonomy actions====="); } String statement = "select * from exo:taxonomyAction where (exo:targetPath like '%/sites content/live/%' or exo:storeHomePath like '%/sites content/live/%')"; QueryResult result = session.getWorkspace().getQueryManager().createQuery(statement, Query.SQL).execute(); NodeIterator nodeIter = result.getNodes(); while(nodeIter.hasNext()) { Node taxoAction = nodeIter.nextNode(); String targetPath = taxoAction.getProperty("exo:targetPath").getString(); String homePath = taxoAction.getProperty("exo:storeHomePath").getString(); taxoAction.setProperty("exo:targetPath", StringUtils.replace(targetPath, "/sites content/live/", "/sites/")); taxoAction.setProperty("exo:storeHomePath", StringUtils.replace(homePath, "/sites content/live/", "/sites/")); } session.save(); if (LOG.isInfoEnabled()) { LOG.info("=====Completed the migration for taxonomy action====="); } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("An unexpected error occurs when migrating for taxonomy actions: ", e); } } finally { if (sessionProvider != null) { sessionProvider.close(); } } } /** * Migrate preference 'Drive name' of site explorer portlet which should be changed to Collaboration instead of collaboration" */ private void migrateDriveNameOfPortletPreferences() { SessionProvider sessionProvider = null; try { sessionProvider = SessionProvider.createSystemProvider(); Session session = sessionProvider.getSession("portal-system", repoService_.getCurrentRepository()); if (LOG.isInfoEnabled()) { LOG.info("=====Start migrate portlet preferences drive name====="); } String statement = "select * from mop:portletpreference where exo:name='mop:driveName' and mop:value='collaboration'"; QueryResult result = session.getWorkspace().getQueryManager().createQuery(statement, Query.SQL).execute(); NodeIterator nodeIter = result.getNodes(); while(nodeIter.hasNext()) { Node preferenceNode = nodeIter.nextNode(); preferenceNode.setProperty("mop:value", new String[]{"Collaboration"}); } session.save(); if (LOG.isInfoEnabled()) { LOG.info("===== Preference drive name have been upgrade completed ====="); } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("An unexpected error occurs when migrating preferences drive name: ", e); } } finally { if (sessionProvider != null) { sessionProvider.close(); } } } }