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.plugins.core.impl.user.population;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.component.Component;
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.authentication.CredentialProvider;
029import org.ametys.core.authentication.CredentialProviderFactory;
030import org.ametys.core.authentication.CredentialProviderModel;
031import org.ametys.core.datasource.DataSourceConsumer;
032import org.ametys.core.datasource.SQLDataSourceManager;
033import org.ametys.core.user.directory.UserDirectory;
034import org.ametys.core.user.directory.UserDirectoryFactory;
035import org.ametys.core.user.directory.UserDirectoryModel;
036import org.ametys.core.user.population.UserPopulation;
037import org.ametys.core.user.population.UserPopulationDAO;
038import org.ametys.runtime.model.ElementDefinition;
039import org.ametys.runtime.model.type.ModelItemTypeConstants;
040
041/**
042 * Implementation of {@link DataSourceConsumer} allowing to know whether a data source is used by the populations or not.
043 * It also allows to retrieve the data source ids that are currently in use.
044 */
045public class PopulationDataSourceConsumer implements DataSourceConsumer, Component, Serviceable
046{
047    /** Avalon Role */
048    public static final String ROLE = PopulationDataSourceConsumer.class.getName();
049    
050    /** The DAO for {@link UserPopulation}s */
051    private UserPopulationDAO _userPopulationDAO;
052    
053    /** The user directories factory  */
054    private UserDirectoryFactory _userDirectoryFactory;
055
056    /** The credential providers factory  */
057    private CredentialProviderFactory _credentialProviderFactory;
058    
059    @Override
060    public void service(ServiceManager manager) throws ServiceException
061    {
062        _userPopulationDAO = (UserPopulationDAO) manager.lookup(UserPopulationDAO.ROLE);
063        _userDirectoryFactory = (UserDirectoryFactory) manager.lookup(UserDirectoryFactory.ROLE);
064        _credentialProviderFactory = (CredentialProviderFactory) manager.lookup(CredentialProviderFactory.ROLE);
065    }
066    
067    @Override
068    public TypeOfUse isInUse(String id)
069    {
070        return TypeOfUse.merge(SQLDataSourceManager.AMETYS_INTERNAL_DATASOURCE_ID.equals(id) ? TypeOfUse.BLOCKING : TypeOfUse.NOT_USED, _isInUseByUserDirectories(id), _isInUseByCredentialProviders(id));
071    }
072    
073    private TypeOfUse _isInUseByUserDirectories(String id)
074    {
075        for (String udModelId : _userDirectoryFactory.getExtensionsIds())
076        {
077            UserDirectoryModel udModel = _userDirectoryFactory.getExtension(udModelId);
078            
079            // for this model, which parameters are of type "datasource"
080            List<String> datasourceParameters = new ArrayList<>();
081            Map<String, ? extends ElementDefinition> parameters = udModel.getParameters();
082            for (String parameterId : parameters.keySet())
083            {
084                if (ModelItemTypeConstants.DATASOURCE_ELEMENT_TYPE_ID.equals(parameters.get(parameterId).getType().getId()))
085                {
086                    datasourceParameters.add(parameterId);
087                }
088            }
089            
090            // search the user directories of this model
091            for (UserPopulation population : _userPopulationDAO.getUserPopulations(false)) // Admin uses internal, no need to test
092            {
093                for (UserDirectory userDirectory : population.getUserDirectories())
094                {
095                    if (userDirectory.getUserDirectoryModelId().equals(udModelId))
096                    {
097                        for (String datasourceParameter : datasourceParameters)
098                        {
099                            // return true if it is the datasource id we're looking for, continue otherwise
100                            if (id.equals(userDirectory.getParameterValues().get(datasourceParameter)))
101                            {
102                                return TypeOfUse.BLOCKING; // FIXME RUNTIME-3211 the type of use should be blocking only if the population is itself used
103                            }
104                        }
105                    }
106                }
107            }
108        }
109        
110        return TypeOfUse.NOT_USED;
111    }
112    
113    private TypeOfUse _isInUseByCredentialProviders(String id)
114    {
115        for (String cpModelId : _credentialProviderFactory.getExtensionsIds())
116        {
117            CredentialProviderModel cpModel = _credentialProviderFactory.getExtension(cpModelId);
118            
119            // for this model, which parameters are of type "datasource"
120            List<String> datasourceParameters = new ArrayList<>();
121            Map<String, ? extends ElementDefinition> parameters = cpModel.getParameters();
122            for (String parameterId : parameters.keySet())
123            {
124                if (ModelItemTypeConstants.DATASOURCE_ELEMENT_TYPE_ID.equals(parameters.get(parameterId).getType().getId()))
125                {
126                    datasourceParameters.add(parameterId);
127                }
128            }
129            
130            // search the credential providers of this model
131            for (UserPopulation population : _userPopulationDAO.getUserPopulations(false)) // Admin uses internal, no need to test
132            {
133                for (CredentialProvider credentialProvider : population.getCredentialProviders())
134                {
135                    if (credentialProvider.getCredentialProviderModelId().equals(cpModelId))
136                    {
137                        for (String datasourceParameter : datasourceParameters)
138                        {
139                            // return true if it is the datasource id we're looking for, continue otherwise
140                            if (id.equals(credentialProvider.getParameterValues().get(datasourceParameter)))
141                            {
142                                return TypeOfUse.BLOCKING; // FIXME RUNTIME-3211 the type of use should be blocking only if the population is itself used
143                            }
144                        }
145                    }
146                }
147            }
148        }
149        
150        return TypeOfUse.NOT_USED;
151    }
152
153    @Override
154    public Map<String, TypeOfUse> getUsedDataSourceIds()
155    {
156        Map<String, TypeOfUse> result = new HashMap<>();
157        result.put(SQLDataSourceManager.AMETYS_INTERNAL_DATASOURCE_ID, TypeOfUse.BLOCKING);
158
159        for (String udModelId : _userDirectoryFactory.getExtensionsIds())
160        {
161            UserDirectoryModel udModel = _userDirectoryFactory.getExtension(udModelId);
162            
163            // for this model, which parameters are of type "datasource"
164            List<String> datasourceParameters = new ArrayList<>();
165            Map<String, ? extends ElementDefinition> parameters = udModel.getParameters();
166            for (String parameterId : parameters.keySet())
167            {
168                if (ModelItemTypeConstants.DATASOURCE_ELEMENT_TYPE_ID.equals(parameters.get(parameterId).getType().getId()))
169                {
170                    datasourceParameters.add(parameterId);
171                }
172            }
173            
174            // search the user directories of this model
175            for (UserPopulation population : _userPopulationDAO.getUserPopulations(false)) // admin uses internal
176            {
177                for (UserDirectory userDirectory : population.getUserDirectories())
178                {
179                    if (userDirectory.getUserDirectoryModelId().equals(udModelId))
180                    {
181                        for (String datasourceParameter : datasourceParameters)
182                        {
183                            // this datasource value is used
184                            // FIXME the type of use should be blocking only if the population is itself used
185                            result.put((String) userDirectory.getParameterValues().get(datasourceParameter), TypeOfUse.BLOCKING);
186                        }
187                    }
188                }
189            }
190        }
191        
192        // same procedure for credential providers
193        for (String cpModelId : _credentialProviderFactory.getExtensionsIds())
194        {
195            CredentialProviderModel cpModel = _credentialProviderFactory.getExtension(cpModelId);
196            
197            // for this model, which parameters are of type "datasource"
198            List<String> datasourceParameters = new ArrayList<>();
199            Map<String, ? extends ElementDefinition> parameters = cpModel.getParameters();
200            for (String parameterId : parameters.keySet())
201            {
202                if (ModelItemTypeConstants.DATASOURCE_ELEMENT_TYPE_ID.equals(parameters.get(parameterId).getType().getId()))
203                {
204                    datasourceParameters.add(parameterId);
205                }
206            }
207            
208            // search the credential providers of this model
209            for (UserPopulation population : _userPopulationDAO.getUserPopulations(false)) // admin uses internal
210            {
211                for (CredentialProvider credentialProvider : population.getCredentialProviders())
212                {
213                    if (credentialProvider.getCredentialProviderModelId().equals(cpModelId))
214                    {
215                        for (String datasourceParameter : datasourceParameters)
216                        {
217                            // this datasource value is used
218                            // FIXME the type of use should be blocking only if the population is itself used
219                            result.put((String) credentialProvider.getParameterValues().get(datasourceParameter), TypeOfUse.BLOCKING);
220                        }
221                    }
222                }
223            }
224        }
225        
226        return result;
227    }
228}