001/*
002 *  Copyright 2020 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.plugins.repository.migration.jcr;
017
018import java.util.HashSet;
019import java.util.Set;
020
021import org.apache.avalon.framework.component.Component;
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.avalon.framework.service.Serviceable;
025
026import org.ametys.plugins.repository.AmetysObjectResolver;
027import org.ametys.plugins.repository.AmetysRepositoryException;
028import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
029import org.ametys.plugins.repository.UnknownAmetysObjectException;
030import org.ametys.plugins.repository.migration.jcr.repository.VersionsAmetysObject;
031import org.ametys.plugins.repository.migration.jcr.repository.VersionsFactory;
032import org.ametys.runtime.plugin.PluginsManager;
033
034/**
035 * A helper for the root versions object.
036 */
037public class VersionsRootHelper implements Component, Serviceable
038{
039    /** Avalon Role */
040    public static final String ROLE = VersionsRootHelper.class.getName();
041    
042    /** The Ametys object resolver */
043    protected AmetysObjectResolver _resolver;
044    
045    @Override
046    public void service(ServiceManager manager) throws ServiceException
047    {
048        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
049    }
050
051    /**
052     * <code>true</code> if the root object to store versions is present. It's the node /ametys:versions.
053     * @return <code>true</code> if the root object to store versions is present, otherwise <code>false</code>.
054     * @throws AmetysRepositoryException if an error occurs
055     */
056    public boolean hasRootObject() throws AmetysRepositoryException
057    {
058        try
059        {
060            _resolver.resolveByPath("/" + VersionsFactory.VERSIONS_NODENAME);
061            return true;
062        }
063        catch (UnknownAmetysObjectException e)
064        {
065            return false;
066        }
067        catch (AmetysRepositoryException e)
068        {
069            throw new AmetysRepositoryException("Unable to get the versions root node", e);
070        }
071    }
072
073    /**
074     * Get or create the root object to store versions. It's the node /ametys:versions.
075     * @return the root object to store versions
076     * @throws AmetysRepositoryException if an error occurs
077     */
078    public VersionsAmetysObject getRootObject() throws AmetysRepositoryException
079    {
080        try
081        {
082            ModifiableTraversableAmetysObject rootNode = _resolver.resolveByPath("/");
083            if (rootNode.hasChild(VersionsFactory.VERSIONS_NODENAME))
084            {
085                return rootNode.getChild(VersionsFactory.VERSIONS_NODENAME);
086            }
087            
088            VersionsAmetysObject versionsNode = rootNode.createChild(VersionsFactory.VERSIONS_NODENAME, VersionsFactory.VERSIONS_NODETYPE);
089            rootNode.saveChanges();
090            return versionsNode;
091        }
092        catch (AmetysRepositoryException e)
093        {
094            throw new AmetysRepositoryException("Unable to get the versions root node", e);
095        }
096    }
097
098    /**
099     * <code>true</code> if the repository has registered plugins. Read the attribute /ametys:versions/@ametys:knownPlugins.
100     * @return <code>true</code> if there is at least one registered plugin
101     */
102    public boolean hasKnownPlugins()
103    {
104        return !getRootObject().getKnownPlugins().isEmpty();
105    }
106    
107    /**
108     * <code>true</code> if the repository has already been launched with this plugin before. Read the attribute /ametys:versions/@ametys:knownPlugins.
109     * @param plugin the name of the plugin
110     * @return <code>true</code> if the plugin is already known
111     */
112    public boolean isAKnownPlugin(String plugin)
113    {
114        return getRootObject().getKnownPlugins().contains(plugin);
115    }
116
117    /**
118     * Update the plugin names in the root versions object. Write the attribute /ametys:versions/@ametys:knownPlugins.
119     * Make sure not to "forget" plugins that are not here anymore, for example if we are in safe mode, there can be less plugins and that might cause problem if some extensions have failOnOldData.
120     */
121    public void updateKnownPlugins()
122    {
123        Set<String> plugins = PluginsManager.getInstance().getPluginNames();
124        VersionsAmetysObject root = getRootObject();
125        Set<String> knownPlugins = root.getKnownPlugins();
126        
127        Set<String> fullList = new HashSet<>();
128        fullList.addAll(knownPlugins);
129        fullList.addAll(plugins);
130        
131        root.setKnownPlugins(fullList);
132        root.saveChanges();
133    }
134}