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.core.migration;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import org.apache.avalon.framework.configuration.Configurable;
022import org.apache.avalon.framework.configuration.Configuration;
023import org.apache.avalon.framework.configuration.ConfigurationException;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027
028import org.ametys.core.migration.MigrationEngine.MigrationComponent;
029import org.ametys.core.migration.action.Action;
030import org.ametys.core.migration.action.ActionConfiguration;
031import org.ametys.core.migration.action.ActionExtensionPoint;
032import org.ametys.core.migration.version.VersionConfiguration;
033import org.ametys.core.migration.version.handler.VersionHandler;
034import org.ametys.core.migration.version.handler.VersionHandlerExtensionPoint;
035import org.ametys.core.migration.version.storage.VersionStorage;
036import org.ametys.runtime.plugin.AbstractExtensionPoint;
037
038/**
039 * Migration Extension Point that will list all migration needed by the current state of the application
040 */
041public class MigrationExtensionPoint extends AbstractExtensionPoint<MigrationComponent> implements Serviceable, Configurable
042{
043    /** Avalon Role */
044    public static final String ROLE = MigrationExtensionPoint.class.getName();
045    
046    private VersionHandlerExtensionPoint _versionHandlerEP;
047
048    private ActionExtensionPoint _upgradeEP;
049    private ActionExtensionPoint _initializationEP;
050    
051    private boolean _internal;
052    
053    public void service(ServiceManager manager) throws ServiceException
054    {
055        _versionHandlerEP = (VersionHandlerExtensionPoint) manager.lookup(VersionHandlerExtensionPoint.ROLE);
056        _upgradeEP = (ActionExtensionPoint) manager.lookup(ActionExtensionPoint.ROLE_UPGRADE);
057        _initializationEP = (ActionExtensionPoint) manager.lookup(ActionExtensionPoint.ROLE_INITIALIZATION);
058    }
059    
060    public void configure(Configuration configuration) throws ConfigurationException
061    {
062        _internal = configuration.getChild("internal").getValueAsBoolean(false);
063    }
064    
065    public void addExtension(String id, String pluginName, String featureName, Configuration configuration) throws ConfigurationException
066    {
067        // Get VersionHandler, its associated VersionStorage and their VersionConfiguration
068        Configuration versionsConfiguration = configuration.getChild("versions");
069        String versionHandlerType = configuration.getChild("versions").getAttribute("type");
070        VersionHandler handler = _versionHandlerEP.getExtension(versionHandlerType);
071        
072        VersionConfiguration handlerConfiguration;
073        VersionStorage storage;
074        try
075        {
076            handlerConfiguration = handler.createVersionConfiguration(versionsConfiguration);
077            storage = handler.getVersionStorage(handlerConfiguration);
078        }
079        catch (NotMigrableInSafeModeException e)
080        {
081            getLogger().warn("The migration '{}' cannot be done in safe mode", id, e);
082            return;
083        }
084        catch (MigrationException e)
085        {
086            getLogger().warn("Unable to find storage for  migration '{}'", id, e);
087            return;
088        }
089
090        List<ActionConfiguration> upgrades = new ArrayList<>();
091        
092        Configuration[] upgradeList = configuration.getChild("upgrades").getChildren("upgrade");
093        for (Configuration upgradeConf : upgradeList)
094        {
095            String upgradeVersionNumber = upgradeConf.getAttribute("versionNumber");
096            String type = upgradeConf.getAttribute("type");
097            String from = upgradeConf.getAttribute("from", null);
098            String comment = upgradeConf.getAttribute("comment", null);
099            boolean restartRequired = upgradeConf.getAttributeAsBoolean("restart", false);
100            
101            Action action = _upgradeEP.getExtension(type);
102            
103            if (action == null)
104            {
105                throw new ConfigurationException("The type '" + type + "' does not exist.", upgradeConf);
106            }
107            
108            upgrades.add(action.createActionConfiguration(upgradeVersionNumber, type, comment, from, restartRequired, false, upgradeConf));
109        }
110        
111        ActionConfiguration initialization = null;
112        
113        Configuration initializationConf = configuration.getChild("initialization", false);
114        if (initializationConf != null)
115        {
116            String type = initializationConf.getAttribute("type");
117            String comment = initializationConf.getAttribute("comment", null);
118            boolean restartRequired = initializationConf.getAttributeAsBoolean("restart", false);
119            
120            Action action = _initializationEP.getExtension(type);
121            
122            if (action == null)
123            {
124                throw new ConfigurationException("The type '" + type + "' does not exist.", initializationConf);
125            }
126            
127            initialization = action.createActionConfiguration(null, type, comment, null, restartRequired, true, initializationConf);
128        }
129        
130        _extensions.put(id, new MigrationComponent(id, _internal, pluginName, featureName, versionHandlerType, handler, storage, handlerConfiguration, initialization, upgrades));
131    }
132
133    public void initializeExtensions() throws Exception
134    {
135        // Nothing here
136    }
137}