/* * Copyright (C) 2009 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.services.jcr.ext.hierarchy.impl; import org.exoplatform.commons.utils.PropertyManager; import org.exoplatform.container.component.ComponentPlugin; import org.exoplatform.container.xml.InitParams; import org.exoplatform.services.jcr.RepositoryService; import org.exoplatform.services.jcr.core.ManageableRepository; import org.exoplatform.services.jcr.ext.common.SessionProvider; import org.exoplatform.services.jcr.ext.distribution.DataDistributionManager; import org.exoplatform.services.jcr.ext.distribution.DataDistributionMode; import org.exoplatform.services.jcr.ext.distribution.DataDistributionType; import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator; import org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig.JcrPath; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.picocontainer.Startable; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.jcr.Node; import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; import javax.jcr.Session; /** * * Created by The eXo Platform SAS Author : Dang Van Minh minh.dang@exoplatform.com Nov 15, 2007 * 2:21:57 PM */ public class NodeHierarchyCreatorImpl implements NodeHierarchyCreator, Startable { private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.ext.NodeHierarchyCreatorImpl"); private static final String USERS_PATH = "usersPath"; private static final String USER_APPLICATION = "userApplicationData"; private static final String PUBLIC_APPLICATION = "eXoApplications"; private static final String USER_PRIVATE = "userPrivate"; private static final String USER_PUBLIC = "userPublic"; private final RepositoryService jcrService_; private final DataDistributionManager dataDistributionManager_; private final List<AddPathPlugin> pathPlugins_ = new ArrayList<AddPathPlugin>(); private final Map<String, String> paths_ = new HashMap<String, String>(); private final boolean oldDistribution; private final boolean autoMigrate; public NodeHierarchyCreatorImpl(RepositoryService jcrService, InitParams params) { this(jcrService, null, params); } public NodeHierarchyCreatorImpl(RepositoryService jcrService, DataDistributionManager dataDistributionManager, InitParams params) { if (dataDistributionManager == null) { throw new IllegalArgumentException("The DataDistributionManager is now mandatory if you use the " + "NodeHierarchyCreator, so please define it in your configuration " + "as described in the JCR documentation"); } jcrService_ = jcrService; dataDistributionManager_ = dataDistributionManager; oldDistribution = params != null && params.getValueParam("old-user-distribution") != null && Boolean.valueOf(params.getValueParam("old-user-distribution").getValue()); autoMigrate = params != null && params.getValueParam("auto-migrate") != null && Boolean.valueOf(params.getValueParam("auto-migrate").getValue()); if (PropertyManager.isDevelopping() && !oldDistribution) { LOG.info("The NodeHierarchyCreator is configured to use the new distribution mechanism for the" + " users directories, if you prefer to use the old mechanism set the value parameter " + "'old-user-distribution' to 'true'."); } } /** * {@inheritDoc} */ public void start() { try { processAddPathPlugin(); } catch (Exception e) { LOG.error("An error occurs while processing the plugins", e); } if (isNeededToMigrate()) { try { migrate(); } catch (RepositoryException e) { LOG.error("An error occurs while upgrading JCR structure", e); } } } /** * {@inheritDoc} */ public void stop() { } /** * {@inheritDoc} */ public void init(String repository) throws Exception { initBasePath(repository); } /** * {@inheritDoc} */ public void init() throws Exception { initBasePath(null); } private void createNode(Node rootNode, String path, String nodeType, List<String> mixinTypes, Map<String, String[]> permissions) throws Exception { dataDistributionManager_.getDataDistributionType(DataDistributionMode.NONE).getOrCreateDataNode(rootNode, path, nodeType, mixinTypes, permissions); } private void processAddPathPlugin() throws Exception { Session session = null; for (AddPathPlugin pathPlugin : pathPlugins_) { HierarchyConfig hierarchyConfig = pathPlugin.getPaths(); if (hierarchyConfig == null) { continue; } List<JcrPath> jcrPaths = hierarchyConfig.getJcrPaths(); if (jcrPaths == null) { continue; } Set<String> workspaceNames = new LinkedHashSet<String>(); if (hierarchyConfig.getWorkspaces() != null) { workspaceNames.addAll(hierarchyConfig.getWorkspaces()); } String repositoryName = hierarchyConfig.getRepository(); ManageableRepository repository = repositoryName == null || repositoryName.isEmpty() ? jcrService_.getCurrentRepository() : jcrService_.getRepository(repositoryName); for (String workspaceName : workspaceNames) { JcrPath currentjcrPath = null; try { session = repository.getSystemSession(workspaceName); Node rootNode = session.getRootNode(); for (JcrPath jcrPath : jcrPaths) { currentjcrPath = jcrPath; if (!jcrPath.getAlias().equals(USER_APPLICATION) && !jcrPath.getAlias().startsWith(USER_PRIVATE) && !jcrPath.getAlias().startsWith(USER_PUBLIC)) { createNode(rootNode, jcrPath.getPath(), jcrPath.getNodeType(), jcrPath.getMixinTypes(), jcrPath.getPermissions(null)); } } } catch (RepositoryException e) { LOG.error("An error occurs while processing the JCR path which alias is " + (currentjcrPath == null ? null : currentjcrPath.getAlias()) + " with the workspace " + workspaceName, e); } finally { if (session != null) { session.logout(); session = null; } } } } } private void initBasePath(String repositoryName) throws Exception { Session session = null; ManageableRepository manageableRepository = repositoryName == null || repositoryName.isEmpty() ? jcrService_.getCurrentRepository() : jcrService_ .getRepository(repositoryName); String defaultWorkspace = manageableRepository.getConfiguration().getDefaultWorkspaceName(); String systemWorkspace = manageableRepository.getConfiguration().getSystemWorkspaceName(); boolean isSameWorkspace = defaultWorkspace.equalsIgnoreCase(systemWorkspace); String[] workspaceNames = manageableRepository.getWorkspaceNames(); for (AddPathPlugin pathPlugin : pathPlugins_) { HierarchyConfig hierarchyConfig = pathPlugin.getPaths(); if (hierarchyConfig == null) { continue; } List<JcrPath> jcrPaths = hierarchyConfig.getJcrPaths(); if (jcrPaths == null) { continue; } for (String workspaceName : workspaceNames) { if (!isSameWorkspace && workspaceName.equalsIgnoreCase(systemWorkspace)) continue; JcrPath currentjcrPath = null; try { session = manageableRepository.getSystemSession(workspaceName); Node rootNode = session.getRootNode(); for (JcrPath jcrPath : jcrPaths) { currentjcrPath = jcrPath; if (!jcrPath.getAlias().equals(USER_APPLICATION) && !jcrPath.getAlias().startsWith(USER_PRIVATE) && !jcrPath.getAlias().startsWith(USER_PUBLIC)) { createNode(rootNode, jcrPath.getPath(), jcrPath.getNodeType(), jcrPath.getMixinTypes(), jcrPath.getPermissions(null)); } } } catch (Exception e) { LOG.error("An error occurs while processing the JCR path which alias is " + (currentjcrPath == null ? null : currentjcrPath.getAlias()) + " with the workspace " + workspaceName, e); } finally { if (session != null) { session.logout(); session = null; } } } } } /** * {@inheritDoc} */ public Node getUserApplicationNode(SessionProvider sessionProvider, String userName) throws Exception { Node userNode = getUserNode(sessionProvider, userName); return dataDistributionManager_.getDataDistributionType(DataDistributionMode.NONE).getOrCreateDataNode(userNode, getJcrPath(USER_APPLICATION)); } /** * {@inheritDoc} */ public Node getPublicApplicationNode(SessionProvider sessionProvider) throws Exception { Session session = getSession(sessionProvider); Node rootNode = session.getRootNode(); return dataDistributionManager_.getDataDistributionType(DataDistributionMode.NONE).getDataNode(rootNode, getJcrPath(PUBLIC_APPLICATION)); } /** * {@inheritDoc} */ public Node getUserNode(SessionProvider sessionProvider, String userName) throws Exception { Session session = getSession(sessionProvider); Node usersNode = getRootOfUsersNodes(session); DataDistributionType type = dataDistributionManager_.getDataDistributionType(oldDistribution ? DataDistributionMode.NONE : DataDistributionMode.READABLE); return type.getOrCreateDataNode(usersNode, userName); } /** * {@inheritDoc} */ public void removeUserNode(SessionProvider sessionProvider, String userName) throws Exception { Session session = getSession(sessionProvider); try { Node usersNode = getRootOfUsersNodes(session); DataDistributionType type = dataDistributionManager_.getDataDistributionType(oldDistribution ? DataDistributionMode.NONE : DataDistributionMode.READABLE); type.removeDataNode(usersNode, userName); } catch (PathNotFoundException e) { if (LOG.isTraceEnabled()) { LOG.trace("An exception occurred: " + e.getMessage()); } } } private Session getSession(SessionProvider sessionProvider) throws RepositoryException { ManageableRepository repo = jcrService_.getCurrentRepository(); return sessionProvider.getSession(repo.getConfiguration().getDefaultWorkspaceName(), repo); } /** * {@inheritDoc} */ public String getJcrPath(String alias) { return paths_.get(alias); } /** * {@inheritDoc} */ public void addPlugin(ComponentPlugin plugin) { if (plugin instanceof AddPathPlugin) { AddPathPlugin app = (AddPathPlugin)plugin; pathPlugins_.add(app); if (app.getPaths() != null && app.getPaths().getJcrPaths() != null) { for (JcrPath jcrPath : app.getPaths().getJcrPaths()) { if (jcrPath.getAlias() != null && jcrPath.getPath() != null) { paths_.put(jcrPath.getAlias(), jcrPath.getPath()); } } } } } private boolean isNeededToMigrate() { return !oldDistribution && autoMigrate; } private void migrate() throws RepositoryException { Session session = getSession(SessionProvider.createSystemProvider()); try { Node rootNode = getRootOfUsersNodes(session); dataDistributionManager_.getDataDistributionType(DataDistributionMode.READABLE).migrate(rootNode); } finally { session.logout(); } } private Node getRootOfUsersNodes(Session session) throws PathNotFoundException, RepositoryException { String usersPath = getJcrPath(USERS_PATH); return (Node)session.getItem(usersPath); } }