001/*
002 *  Copyright 2010 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.web.live;
017
018import javax.jcr.Node;
019import javax.jcr.RepositoryException;
020import javax.jcr.Session;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.avalon.framework.service.Serviceable;
025import org.apache.commons.lang3.StringUtils;
026
027import org.ametys.cms.repository.Content;
028import org.ametys.plugins.repository.AmetysObjectIterable;
029import org.ametys.plugins.repository.AmetysObjectResolver;
030import org.ametys.plugins.repository.RepositoryConstants;
031import org.ametys.plugins.repository.collection.AmetysObjectCollection;
032import org.ametys.plugins.repository.jcr.JCRAmetysObject;
033import org.ametys.runtime.plugin.component.AbstractLogEnabled;
034import org.ametys.web.synchronization.SynchronizeComponent;
035
036/**
037 * {@link LivePopulator} for synchronizing '/ametys:root/ametys:contents'.
038 */
039public class ContentsLivePopulator extends AbstractLogEnabled implements LivePopulator, Serviceable
040{
041    /** The synchronize helper */
042    protected SynchronizeComponent _synchronizeHelper;
043    /** The Ametys resolver */
044    protected AmetysObjectResolver _resolver;
045
046    @Override
047    public void service(ServiceManager smanager) throws ServiceException
048    {
049        _synchronizeHelper = (SynchronizeComponent) smanager.lookup(SynchronizeComponent.ROLE);
050        _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE);
051    }
052    
053    @Override
054    public void populate(Session session, Session liveSession) throws Exception
055    {
056        Node contentsNode = session.getRootNode().getNode("ametys:root/ametys:contents");
057        
058        Node liveRootNode = liveSession.getRootNode().getNode(AmetysObjectResolver.ROOT_REPO);
059        
060        if (liveRootNode.hasNode("ametys:contents"))
061        {
062            liveRootNode.getNode("ametys:contents").remove();
063        }
064        
065        Node clonedParentNode = _synchronizeHelper.cloneAncestorsAndPreserveUUID(contentsNode, liveSession);
066        _synchronizeHelper.addNodeWithUUID(contentsNode, clonedParentNode, contentsNode.getName());
067        
068        _cloneContents(contentsNode, liveSession);
069    }
070    
071    /**
072     * Clone contents in live workspace
073     * @param contentsNode The root contents node
074     * @param liveSession The live session
075     * @throws RepositoryException if failed to clone contents in live
076     */
077    protected void _cloneContents(Node contentsNode, Session liveSession) throws RepositoryException
078    {
079        _synchronizeHelper.synchronizeACL(contentsNode, liveSession);
080        
081        // Clone the contents.
082        AmetysObjectIterable<Content> contents = _getContents(contentsNode);
083        
084        getLogger().info("Synchronizing {} shared contents at path {}", contents.getSize(), contentsNode.getPath());
085        
086        for (Content content : contents)
087        {
088            if (content instanceof JCRAmetysObject)
089            {
090                _synchronizeHelper.synchronizeContent(content, liveSession);
091            }
092        }
093        
094        // Only save after all contents (that may reference each others) are cloned
095        liveSession.save();
096    }
097    
098    /**
099     * Get the contents of root contents node
100     * @param contentsNode The root contents node
101     * @return The child contents
102     * @throws RepositoryException if failed to get the child contents
103     */
104    protected AmetysObjectIterable<Content> _getContents(Node contentsNode) throws RepositoryException
105    {
106        String contentsPath = StringUtils.substringAfter(contentsNode.getPath(), "/" + RepositoryConstants.NAMESPACE_PREFIX + ":root");
107        
108        AmetysObjectCollection rootContents = _resolver.resolveByPath(contentsPath);
109        return rootContents.getChildren();
110    }
111
112}