/* * 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.services.wcm.category; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.jcr.Node; import javax.jcr.Session; import javax.jcr.Workspace; import javax.jcr.nodetype.NodeType; import javax.jcr.nodetype.PropertyDefinition; import org.apache.commons.lang.StringUtils; import org.exoplatform.container.configuration.ConfigurationManager; import org.exoplatform.container.xml.InitParams; import org.exoplatform.container.xml.ObjectParameter; import org.exoplatform.container.xml.ValueParam; import org.exoplatform.services.cms.BasePath; import org.exoplatform.services.cms.JcrInputProperty; import org.exoplatform.services.cms.actions.ActionServiceContainer; import org.exoplatform.services.cms.actions.impl.ActionConfig; import org.exoplatform.services.cms.actions.impl.ActionConfig.TaxonomyAction; import org.exoplatform.services.cms.impl.DMSConfiguration; import org.exoplatform.services.cms.impl.DMSRepositoryConfiguration; import org.exoplatform.services.cms.impl.Utils; import org.exoplatform.services.cms.link.LinkManager; import org.exoplatform.services.cms.taxonomy.TaxonomyService; import org.exoplatform.services.cms.taxonomy.impl.TaxonomyAlreadyExistsException; import org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig; import org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig.Permission; import org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig.Taxonomy; import org.exoplatform.services.jcr.RepositoryService; import org.exoplatform.services.jcr.access.PermissionType; import org.exoplatform.services.jcr.core.ExtendedNode; import org.exoplatform.services.jcr.core.ManageableRepository; import org.exoplatform.services.jcr.ext.common.SessionProvider; import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.wcm.portal.artifacts.CreatePortalPlugin; import org.exoplatform.services.wcm.utils.WCMCoreUtils; /** * Created by The eXo Platform SAS * Author : eXoPlatform * chuong_phan@exoplatform.com, phan.le.thanh.chuong@gmail.com * Aug 11, 2009 */ public class CreateTaxonomyPlugin extends CreatePortalPlugin { private static final Log LOG = ExoLogger.getLogger(CreateTaxonomyPlugin.class.getName()); public static final String MIX_AFFECTED_NODETYPE = "mix:affectedNodeTypes"; public static final String AFFECTED_NODETYPE = "exo:affectedNodeTypeNames"; public static final String ALL_DOCUMENT_TYPES = "ALL_DOCUMENT_TYPES"; /** The workspace. */ private String workspace = ""; /** The path. */ private String path = ""; /** The tree name. */ private String treeName = ""; /** The permissions. */ private List<Permission> permissions = new ArrayList<Permission>(4); /** The auto create in new repository_. */ private boolean autoCreateWithNewSite_ = false; /** The repository service_. */ private RepositoryService repositoryService; /** The taxonomy service_. */ private TaxonomyService taxonomyService; /** The link manager service_. */ private LinkManager linkManager; /** The base taxonomies storage_. */ private String baseTaxonomiesStorage; /** The base taxonomies definition_. */ private String baseTaxonomiesDefinition; /** The action service container_. */ private ActionServiceContainer actionServiceContainer; /** The params_. */ private InitParams params; /** The dms configuration_. */ private DMSConfiguration dmsConfiguration; /** The name. */ private String name; private String portalName; /** * Instantiates a new initial taxonomy plugin. * * @param params the params * @param configurationManager the configuration manager * @param repositoryService the repository service * @param nodeHierarchyCreator the node hierarchy creator * @param taxonomyService the taxonomy service * @param actionServiceContainer the action service container * @param dmsConfiguration the dms configuration * * @throws Exception the exception */ public CreateTaxonomyPlugin(InitParams params, ConfigurationManager configurationManager, RepositoryService repositoryService, NodeHierarchyCreator nodeHierarchyCreator, TaxonomyService taxonomyService, ActionServiceContainer actionServiceContainer, DMSConfiguration dmsConfiguration, LinkManager linkManager) throws Exception { super(params, configurationManager, repositoryService); this.repositoryService = repositoryService; this.baseTaxonomiesStorage = nodeHierarchyCreator.getJcrPath(BasePath.TAXONOMIES_TREE_STORAGE_PATH); this.baseTaxonomiesDefinition = nodeHierarchyCreator.getJcrPath(BasePath.TAXONOMIES_TREE_DEFINITION_PATH); this.taxonomyService = taxonomyService; this.actionServiceContainer = actionServiceContainer; this.params = params; this.dmsConfiguration = dmsConfiguration; this.linkManager = linkManager; } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.portal.artifacts.BasePortalArtifactsPlugin * #deployToPortal(java.lang.String, * org.exoplatform.services.jcr.ext.common.SessionProvider) */ public void deployToPortal(SessionProvider sessionProvider, String portalName) throws Exception { this.portalName = portalName; ValueParam autoCreated = params.getValueParam("autoCreateWithNewSite"); ValueParam workspaceParam = params.getValueParam("workspace"); ValueParam pathParam = params.getValueParam("path"); ValueParam nameParam = params.getValueParam("treeName"); if (autoCreated != null) autoCreateWithNewSite_ = Boolean.parseBoolean(autoCreated.getValue()); if(!autoCreateWithNewSite_) return; if (pathParam == null || workspaceParam == null || workspaceParam.getValue().trim().length() == 0) { path = baseTaxonomiesStorage; } else { path = pathParam.getValue(); workspace = workspaceParam.getValue(); } if (nameParam != null) { treeName = nameParam.getValue(); } if (treeName.contains("{treeName}")) { treeName = StringUtils.replace(treeName, "{treeName}", portalName); } path = StringUtils.replace(path, "{portalName}", portalName); Session session = null; try { // Get source information Node srcTaxonomy = taxonomyService.getTaxonomyTree(treeName); String srcWorkspace = srcTaxonomy.getSession().getWorkspace().getName(); // Get destination information ManageableRepository repository = repositoryService.getCurrentRepository(); session = sessionProvider.getSession(this.workspace, repository); Workspace destWorkspace = session.getWorkspace(); String destPath = path + "/" + srcTaxonomy.getName(); // If same workspace if (srcWorkspace.equals(destWorkspace.getName())) { destWorkspace.move(srcTaxonomy.getPath(), destPath); } else { // Clone taxonomy tree across workspace destWorkspace.clone(srcWorkspace, srcTaxonomy.getPath(), destPath, true); // Remove old link taxonomy tree in definition String dmsSystemWorkspaceName = dmsConfiguration.getConfig().getSystemWorkspace(); Node taxonomyDefinition = (Node) sessionProvider.getSession(dmsSystemWorkspaceName, repository) .getItem(baseTaxonomiesDefinition); Node srcLinkTaxonomy = taxonomyDefinition.getNode(srcTaxonomy.getName()); srcLinkTaxonomy.remove(); // Remove old taxonomy tree srcTaxonomy.remove(); // Register new taxonomy tree in definition Node destTaxonomy = (Node) session.getItem(destPath); linkManager.createLink(taxonomyDefinition, destTaxonomy); } session.save(); return; } catch (Exception e) { init(); } } /** * Inits the. * * @throws Exception the exception */ public void init() throws Exception { importPredefineTaxonomies(); } /* (non-Javadoc) * @see org.exoplatform.services.deployment.DeploymentPlugin#getName() */ public String getName() { return name; } /* (non-Javadoc) * @see org.exoplatform.services.deployment.DeploymentPlugin#setName(java.lang.String) */ public void setName(String name) { this.name = name; } /** * Gets the path. * * @return the path */ public String getPath() { return path; } /** * Sets the path. * * @param path the new path */ public void setPath(String path) { this.path = path; } /** * Gets the permissions. * * @return the permissions */ public List<Permission> getPermissions() { return permissions; } /** * Sets the permissions. * * @param permissions the new permissions */ public void setPermissions(List<Permission> permissions) { this.permissions = permissions; } /** * Gets the workspace. * * @return the workspace */ public String getWorkspace() { return workspace; } /** * Sets the workspace. * * @param workspace the new workspace */ public void setWorkspace(String workspace) { this.workspace = workspace; } /** * Import predefine taxonomies. * * @param repository the repository * * @throws Exception the exception */ @SuppressWarnings("unchecked") private void importPredefineTaxonomies() throws Exception { ManageableRepository manageableRepository = this.repositoryService.getCurrentRepository(); DMSRepositoryConfiguration dmsRepoConfig = this.dmsConfiguration.getConfig(); if (getWorkspace() == null) { setWorkspace(dmsRepoConfig.getSystemWorkspace()); } Session session = manageableRepository.getSystemSession(getWorkspace()); Node taxonomyStorageNode = (Node) session.getItem(getPath()); if (taxonomyStorageNode.hasProperty("exo:isImportedChildren")) { session.logout(); return; } taxonomyStorageNode.setProperty("exo:isImportedChildren", true); Iterator<ObjectParameter> it = params.getObjectParamIterator(); Node taxonomyStorageNodeSystem = Utils.makePath(taxonomyStorageNode, treeName, "exo:taxonomy", null); session.save(); while (it.hasNext()) { ObjectParameter objectParam = it.next(); if (objectParam.getName().equals("permission.configuration")) { TaxonomyConfig config = (TaxonomyConfig) objectParam.getObject(); for (Taxonomy taxonomy : config.getTaxonomies()) { Map mapPermissions = getPermissions(taxonomy.getPermissions()); if (mapPermissions != null) { ((ExtendedNode) taxonomyStorageNodeSystem).setPermissions(mapPermissions); } if (taxonomyStorageNodeSystem.canAddMixin("mix:referenceable")) { taxonomyStorageNodeSystem.addMixin("mix:referenceable"); } } } else if (objectParam.getName().equals("taxonomy.configuration")) { TaxonomyConfig config = (TaxonomyConfig) objectParam.getObject(); for (Taxonomy taxonomy : config.getTaxonomies()) { Node taxonomyNode = Utils.makePath(taxonomyStorageNodeSystem, taxonomy.getPath(), "exo:taxonomy", getPermissions(taxonomy.getPermissions())); if (taxonomyNode.canAddMixin("mix:referenceable")) { taxonomyNode.addMixin("mix:referenceable"); } if (taxonomyNode.canAddMixin("exo:rss-enable")) { taxonomyNode.addMixin("exo:rss-enable"); } if(StringUtils.isNotEmpty(taxonomy.getTitle())) { taxonomyNode.setProperty("exo:title", taxonomy.getTitle()); } else { taxonomyNode.setProperty("exo:title", taxonomy.getName()); } taxonomyNode.getSession().save(); } } else if (objectParam.getName().equals("predefined.actions")) { ActionConfig config = (ActionConfig) objectParam.getObject(); List actions = config.getActions(); for (Iterator iter = actions.iterator(); iter.hasNext();) { TaxonomyAction action = (TaxonomyAction) iter.next(); addAction(action, taxonomyStorageNodeSystem); } } } taxonomyStorageNode.save(); try { taxonomyService.addTaxonomyTree(taxonomyStorageNodeSystem); } catch (TaxonomyAlreadyExistsException e) { if (LOG.isErrorEnabled()) LOG.error("Cannot add taxonomy tree", e); } session.save(); session.logout(); } /** * Adds the action. * * @param action the action * @param srcNode the src node * @param repository the repository * * @throws Exception the exception */ private void addAction(ActionConfig.TaxonomyAction action, Node srcNode) throws Exception { Map<String, JcrInputProperty> sortedInputs = new HashMap<String, JcrInputProperty>(); JcrInputProperty jcrInputName = new JcrInputProperty(); jcrInputName.setJcrPath("/node/exo:name"); jcrInputName.setValue(action.getName()); sortedInputs.put("/node/exo:name", jcrInputName); JcrInputProperty jcrInputDes = new JcrInputProperty(); jcrInputDes.setJcrPath("/node/exo:description"); jcrInputDes.setValue(action.getDescription()); sortedInputs.put("/node/exo:description", jcrInputDes); JcrInputProperty jcrInputLife = new JcrInputProperty(); jcrInputLife.setJcrPath("/node/exo:lifecyclePhase"); jcrInputLife.setValue(action.getLifecyclePhase().toArray(new String[0])); sortedInputs.put("/node/exo:lifecyclePhase", jcrInputLife); JcrInputProperty jcrInputHomePath = new JcrInputProperty(); jcrInputHomePath.setJcrPath("/node/exo:storeHomePath"); String homepath = action.getHomePath(); homepath = StringUtils.replace(homepath, "{portalName}", portalName); homepath = StringUtils.replace(homepath, "{treeName}", treeName); jcrInputHomePath.setValue(homepath); sortedInputs.put("/node/exo:storeHomePath", jcrInputHomePath); JcrInputProperty jcrInputTargetWspace = new JcrInputProperty(); jcrInputTargetWspace.setJcrPath("/node/exo:targetWorkspace"); jcrInputTargetWspace.setValue(action.getTargetWspace()); sortedInputs.put("/node/exo:targetWorkspace", jcrInputTargetWspace); JcrInputProperty jcrInputTargetPath = new JcrInputProperty(); jcrInputTargetPath.setJcrPath("/node/exo:targetPath"); String targetPath = action.getTargetPath(); targetPath = StringUtils.replace(targetPath, "{portalName}", portalName); jcrInputTargetPath.setValue(targetPath); sortedInputs.put("/node/exo:targetPath", jcrInputTargetPath); JcrInputProperty rootProp = sortedInputs.get("/node"); if (rootProp == null) { rootProp = new JcrInputProperty(); rootProp.setJcrPath("/node"); rootProp.setValue((sortedInputs.get("/node/exo:name")).getValue()); sortedInputs.put("/node", rootProp); } else { rootProp.setValue((sortedInputs.get("/node/exo:name")).getValue()); } actionServiceContainer.addAction(srcNode, action.getType(), sortedInputs); Node actionNode = actionServiceContainer.getAction(srcNode, action.getName()); if (action.getRoles() != null) { String[] roles = StringUtils.split(action.getRoles(), ";"); actionNode.setProperty("exo:roles", roles); } Iterator mixins = action.getMixins().iterator(); NodeType nodeType; String value; ManageableRepository manageableRepository = WCMCoreUtils.getRepository(); while (mixins.hasNext()) { ActionConfig.Mixin mixin = (ActionConfig.Mixin) mixins.next(); actionNode.addMixin(mixin.getName()); Map<String, String> props = mixin.getParsedProperties(); Set keys = props.keySet(); nodeType = manageableRepository.getNodeTypeManager().getNodeType(mixin.getName()); for (Iterator iterator = keys.iterator(); iterator.hasNext();) { String key = (String) iterator.next(); for(PropertyDefinition pro : nodeType.getPropertyDefinitions()) { if (pro.getName().equals(key)) { if (pro.isMultiple()) { value = props.get(key); if (value != null) { actionNode.setProperty(key, value.split(",")); } } else { actionNode.setProperty(key, props.get(key)); } break; } } } } actionNode.getSession().save(); } /** * Gets the permissions. * * @param listPermissions the list permissions * * @return the permissions */ private Map<String, String[]> getPermissions(List<Permission> listPermissions) { Map<String, String[]> permissionsMap = new HashMap<String, String[]>(); for (Permission permission : listPermissions) { StringBuilder strPer = new StringBuilder(); if ("true".equals(permission.getRead())) strPer.append(PermissionType.READ); if ("true".equals(permission.getAddNode())) strPer.append(",").append(PermissionType.ADD_NODE); if ("true".equals(permission.getSetProperty())) strPer.append(",").append(PermissionType.SET_PROPERTY); if ("true".equals(permission.getRemove())) strPer.append(",").append(PermissionType.REMOVE); permissionsMap.put(permission.getIdentity(), strPer.toString().split(",")); } return permissionsMap; } }