001/*
002 *  Copyright 2016 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.script;
017
018import java.sql.Connection;
019import java.util.HashSet;
020import java.util.Set;
021
022import org.apache.avalon.framework.configuration.Configurable;
023import org.apache.avalon.framework.configuration.Configuration;
024import org.apache.avalon.framework.configuration.ConfigurationException;
025import org.apache.avalon.framework.logger.AbstractLogEnabled;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029import org.apache.commons.lang3.StringUtils;
030import org.apache.commons.lang3.Strings;
031import org.apache.excalibur.source.SourceResolver;
032
033import org.ametys.core.datasource.ConnectionHelper;
034import org.ametys.core.datasource.SQLDataSourceManager;
035import org.ametys.runtime.config.Config;
036import org.ametys.runtime.plugin.Init;
037import org.ametys.runtime.plugin.component.PluginAware;
038
039/**
040 * Creates necessary SQL tables (if not already existing) at initialization.
041 */
042public class SqlTablesInit extends AbstractLogEnabled implements Init, Serviceable, Configurable, PluginAware
043{
044    /** Plugin name */
045    protected String _pluginName;
046    
047    /** The data source identifer */
048    protected String _dataSourceId;
049    
050    /** The set of configured table init scripts */
051    protected Set<InitScript> _scripts;
052    
053    /** SQL data source manager */
054    protected SQLDataSourceManager _sqlDataSourceManager;
055    
056    /** Source resolver */
057    protected SourceResolver _sourceResolver;
058    
059    @Override
060    public void setPluginInfo(String pluginName, String featureName, String id)
061    {
062        _pluginName = pluginName;
063    }
064    
065    @Override
066    public void service(ServiceManager manager) throws ServiceException
067    {
068        _sqlDataSourceManager = (SQLDataSourceManager) manager.lookup(SQLDataSourceManager.ROLE);
069        _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
070    }
071    
072    @Override
073    public void configure(Configuration configuration) throws ConfigurationException
074    {
075        Configuration dataSourceConf = configuration.getChild("datasource", false);
076        if (dataSourceConf == null)
077        {
078            throw new ConfigurationException("The 'datasource' configuration node must be defined.", dataSourceConf);
079        }
080        
081        String dataSourceConfParam = dataSourceConf.getValue();
082        String dataSourceConfType = dataSourceConf.getAttribute("type", "config");
083        
084        if (Strings.CS.equals(dataSourceConfType, "config"))
085        {
086            _dataSourceId = Config.getInstance().getValue(dataSourceConfParam);
087        }
088        else // expecting type="id"
089        {
090            _dataSourceId = dataSourceConfParam;
091        }
092        
093        _scripts = new HashSet<>();
094        Configuration[] scripts = configuration.getChildren("script");
095        
096        for (Configuration scriptConf : scripts)
097        {
098            String pluginName = scriptConf.getAttribute("plugin", _pluginName);
099            
100            String testTable = scriptConf.getAttribute("testTable");
101            if (StringUtils.isBlank(testTable))
102            {
103                throw new ConfigurationException("The test table attribute cannot be blank.");
104            }
105            
106            String fileName = scriptConf.getValue();
107            if (StringUtils.isBlank(fileName))
108            {
109                throw new ConfigurationException("The SQL file name cannot be blank.");
110            }
111            
112            _scripts.add(new InitScript(pluginName, fileName, testTable));
113        }
114    }
115    
116    @Override
117    public void init() throws Exception
118    {
119        try
120        {
121            // Test and create tables
122            Connection connection = null;
123            try
124            {
125                connection = ConnectionHelper.getConnection(_dataSourceId);
126                
127                String scriptFolder = ConnectionHelper.getDatabaseType(connection);
128                
129                for (InitScript initScript : _scripts)
130                {
131                    SQLScriptHelper.createTableIfNotExists(connection, initScript._testTable, "plugin:" + initScript._pluginName + "://scripts/" + scriptFolder + "/" + initScript._fileName, _sourceResolver);
132                }
133            }
134            finally
135            {
136                ConnectionHelper.cleanup(connection);
137            }
138        }
139        catch (Exception e)
140        {
141            String errorMsg = String.format("Error during SQL tables initialization for data source id: '%s'.", StringUtils.defaultString(_dataSourceId));
142            getLogger().error(errorMsg, e);
143        }
144    }
145    
146    private static class InitScript
147    {
148        final String _pluginName;
149        final String _fileName;
150        final String _testTable;
151        
152        public InitScript(String pluginNameArg, String fileNameArg, String testTableArg)
153        {
154            _pluginName = pluginNameArg;
155            _fileName = fileNameArg;
156            _testTable = testTableArg;
157        }
158    }
159}