001/*
002 *  Copyright 2023 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.runtime.plugins.admin.statistics;
017
018import java.lang.management.ManagementFactory;
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.List;
022import java.util.Map;
023import java.util.Map.Entry;
024import java.util.TreeMap;
025
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;
030
031import org.ametys.core.authentication.CredentialProvider;
032import org.ametys.core.authentication.CredentialProviderFactory;
033import org.ametys.core.authentication.CredentialProviderModel;
034import org.ametys.core.group.GroupDirectoryDAO;
035import org.ametys.core.group.directory.GroupDirectory;
036import org.ametys.core.group.directory.GroupDirectoryFactory;
037import org.ametys.core.user.directory.UserDirectory;
038import org.ametys.core.user.directory.UserDirectoryFactory;
039import org.ametys.core.user.population.UserPopulation;
040import org.ametys.core.user.population.UserPopulationDAO;
041import org.ametys.core.version.VersionsHandler;
042import org.ametys.runtime.config.Config;
043import org.ametys.runtime.i18n.I18nizableText;
044import org.ametys.runtime.plugin.PluginsManager;
045import org.ametys.runtime.plugin.component.PluginAware;
046
047/**
048 * All statistics of kernel
049 */
050public class KernelStatisticsProvider implements StatisticsProvider, Serviceable, PluginAware
051{
052    private String _id;
053    private VersionsHandler _versionsHandler;
054    private UserPopulationDAO _userPopulationDAO;
055    private UserDirectoryFactory _userDirectoryFactory;
056    private CredentialProviderFactory _credentialProviderFactory;
057    private GroupDirectoryDAO _groupDirectoryDAO;
058    private GroupDirectoryFactory _groupDirectoryFactory;
059
060    public void service(ServiceManager manager) throws ServiceException
061    {
062        _versionsHandler = (VersionsHandler) manager.lookup(VersionsHandler.ROLE);
063        _userPopulationDAO = (UserPopulationDAO) manager.lookup(UserPopulationDAO.ROLE);
064        _userDirectoryFactory = (UserDirectoryFactory) manager.lookup(UserDirectoryFactory.ROLE);
065        _credentialProviderFactory = (CredentialProviderFactory) manager.lookup(CredentialProviderFactory.ROLE);
066        _groupDirectoryDAO = (GroupDirectoryDAO) manager.lookup(GroupDirectoryDAO.ROLE);
067        _groupDirectoryFactory = (GroupDirectoryFactory) manager.lookup(GroupDirectoryFactory.ROLE);
068    }
069    
070    public void setPluginInfo(String pluginName, String featureName, String id)
071    {
072        _id = id;
073    }
074    
075    public Statistics getStatistics()
076    {
077        return new StatisticsNode(
078                _id, 
079                new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_LABEL"),
080                "ametysicon-trademark-ametys",
081                null,
082                List.of(
083                    _getVersionsStatistics(),
084                    _getPluginsStatistics(),
085                    _getConfigurationStatistics(),
086                    _getPopulationsAndGropDirectoriesStatistics(),
087                    _getServerStatistics()
088                ),
089                true
090            );
091    }
092    
093    
094    private Statistics _getServerStatistics()
095    {
096        return new StatisticsNode(
097                "server", 
098                new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_SERVER_LABEL"),
099                "ametysicon-system-server-sync",
100                null,
101                List.of(
102                    new StatisticsValue(
103                        "osname", 
104                        new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_SERVER_OS_LABEL"), 
105                        "ametysicon-system-terminal", 
106                        ManagementFactory.getOperatingSystemMXBean().getName() + " (" + ManagementFactory.getOperatingSystemMXBean().getVersion() + ")"
107                    ),
108                    new StatisticsValue(
109                        "cpu", 
110                        new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_SERVER_CPU_LABEL"), 
111                        "ametysicon-trademark-jackrabbit", 
112                        String.valueOf(ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors()) + " x " + ManagementFactory.getOperatingSystemMXBean().getArch()
113                    ),
114                    new StatisticsValue(
115                        "ram", 
116                        new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_SERVER_RAM_LABEL"), 
117                        "ametysicon-system-sgbd", 
118                        ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax()
119                    ),
120                    new StatisticsValue(
121                        "vmvendor", 
122                        new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_SERVER_VMVENDOR_LABEL"), 
123                        "ametysicon-trademark-jstack", 
124                        System.getProperty("java.vendor") + " " + ManagementFactory.getRuntimeMXBean().getVmName()
125                    ),
126                    new StatisticsValue(
127                        "vmversion", 
128                        new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_SERVER_VMVERSION_LABEL"), 
129                        "ametysicon-trademark-jstack", 
130                        System.getProperty("java.version")
131                    )
132                ),
133                false
134                );
135    }
136    
137    private Statistics _getVersionsStatistics()
138    {
139        return new StatisticsNode(
140            "versions", 
141            new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_VERSIONS_LABEL"),
142            "ametysicon-maths-number-zero-one",
143            null,
144            _getVersionsChildren(),
145            true
146        );
147    }
148    
149    private List<Statistics> _getVersionsChildren()
150    {
151        return _versionsHandler.getVersions().stream()
152            .map(v -> new StatisticsValue(
153                v.getName(), 
154                new I18nizableText(v.getName()), 
155                "ametysicon-trademark-ametys", 
156                v.getVersion())
157            )
158            .map(Statistics.class::cast)
159            .toList();
160    }
161    
162    private Statistics _getPluginsStatistics()
163    {
164        List<String> plugins = new ArrayList<>(PluginsManager.getInstance().getBundledPluginsNames());
165        Collections.sort(plugins);
166        
167        return new StatisticsValue(
168            "plugins", 
169            new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_PLUGINS_LABEL"),
170            "ametysicon-puzzle-piece1",
171            plugins
172        );
173    }
174    
175    private Statistics _getPopulationsAndGropDirectoriesStatistics()
176    {
177        long populations = 0;
178        
179        Map<String, Long> userDirectoriesCount = new TreeMap<>();
180        Map<String, Long> credentialProvidersCount = new TreeMap<>();
181        
182        for (UserPopulation userPopulation : _userPopulationDAO.getUserPopulations(false))
183        {
184            populations++;
185            
186            for (UserDirectory userDirectory : userPopulation.getUserDirectories())
187            {
188                Long value = userDirectoriesCount.getOrDefault(userDirectory.getUserDirectoryModelId(), 0L);
189                userDirectoriesCount.put(userDirectory.getUserDirectoryModelId(), value + 1);
190            }
191            
192            for (CredentialProvider credentialProvider : userPopulation.getCredentialProviders())
193            {
194                Long value = credentialProvidersCount.getOrDefault(credentialProvider.getCredentialProviderModelId(), 0L);
195                credentialProvidersCount.put(credentialProvider.getCredentialProviderModelId(), value + 1);
196            }
197        }
198        
199        List<Statistics> userDirectories = new ArrayList<>();
200        for (Entry<String, Long> entry : userDirectoriesCount.entrySet())
201        {
202            userDirectories.add(new StatisticsValue(
203                entry.getKey(),
204                _userDirectoryFactory.getExtension(entry.getKey()).getLabel(),
205                "ametysicon-body-idcard-white",
206                entry.getValue()
207            ));
208        }
209        
210        List<Statistics> credentialProviders = new ArrayList<>();
211        for (Entry<String, Long> entry : credentialProvidersCount.entrySet())
212        {
213            CredentialProviderModel cp = _credentialProviderFactory.getExtension(entry.getKey());
214            credentialProviders.add(new StatisticsValue(
215                entry.getKey(),
216                cp.getLabel(),
217                StringUtils.defaultIfBlank(cp.getIconGlyph(), "ametysicon-body-idcard-badge"),
218                entry.getValue()
219            ));
220        }
221        
222        long groups = 0;
223
224        Map<String, Long> groupDirectoriesCount = new TreeMap<>();
225        for (GroupDirectory groupDirectory : _groupDirectoryDAO.getGroupDirectories())
226        {
227            groups++;
228            
229            Long value = groupDirectoriesCount.getOrDefault(groupDirectory.getGroupDirectoryModelId(), 0L);
230            groupDirectoriesCount.put(groupDirectory.getGroupDirectoryModelId(), value + 1);
231        }
232        
233        List<Statistics> groupDirectories = new ArrayList<>();
234        for (Entry<String, Long> entry : groupDirectoriesCount.entrySet())
235        {
236            groupDirectories.add(new StatisticsValue(
237                entry.getKey(),
238                _groupDirectoryFactory.getExtension(entry.getKey()).getLabel(),
239                "ametysicon-body-people",
240                entry.getValue()
241            ));
242        }
243        
244        return new StatisticsNode(
245            "populations-groupdirectories", 
246            new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_USERPOPULATIONSANDGROUPDIRECTORIES_LABEL"),
247            "ametysicon-body-group",
248            populations + groups,
249            List.of(
250                new StatisticsNode(
251                    "populations", 
252                    new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_USERPOPULATIONSANDGROUPDIRECTORIES_POPULATIONS_LABEL"),
253                    "ametysicon-body-people",
254                    populations,
255                    List.of(
256                        new StatisticsNode(
257                            "userdirectories", 
258                            new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_USERPOPULATIONSANDGROUPDIRECTORIES_POPULATIONS_USERDIRECTORIES_LABEL"),
259                            "ametysicon-body-idcard-white",
260                            null,
261                            userDirectories,
262                            false
263                        ),
264                        new StatisticsNode(
265                            "credentialproviders", 
266                            new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_USERPOPULATIONSANDGROUPDIRECTORIES_POPULATIONS_CREDENTIALPROVIDERS_LABEL"),
267                            "ametysicon-body-idcard-badge",
268                            null,
269                            credentialProviders,
270                            false
271                        )                                
272                    ),
273                    false
274                ),
275                new StatisticsNode(
276                    "groupdirectories", 
277                    new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_USERPOPULATIONSANDGROUPDIRECTORIES_GROUPDIRECTORIES_LABEL"),
278                    "ametysicon-body-people",
279                    groups,
280                    groupDirectories,
281                    false
282                )
283            ),
284            false
285        );
286    }
287    
288    private StatisticsNode _getConfigurationStatistics()
289    { 
290        boolean configProd = !Config.getInstance().getValue("runtime.mode.dev", false, true);
291        String configCaptchaType = Config.getInstance().getValue("runtime.captcha.type", false, "");
292        Long configMaxUpload = Config.getInstance().getValue("runtime.upload.max-size", false, 0L);
293        boolean configGravatar = Config.getInstance().getValue("runtime.userprofile.imagesource.gravatar", false, true);
294        
295        return new StatisticsNode(
296            "config",
297            new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_CONFIG_LABEL"),
298            "ametysicon-gear39",
299            null,
300            List.of(
301                new StatisticsValue(
302                    "production",
303                    new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_CONFIG_PRODUCTION_LABEL"),
304                    "ametysicon-movie16",
305                    configProd
306                ),
307                new StatisticsValue(
308                    "captcha",
309                    new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_CONFIG_CAPTCHA_LABEL"),
310                    "ametysicon-abecedary4",
311                    configCaptchaType
312                ),
313                new StatisticsValue(
314                    "upload",
315                    new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_CONFIG_UPLOAD_LABEL"),
316                    "ametysicon-arrow-up-from",
317                    configMaxUpload
318                ),
319                new StatisticsValue(
320                    "gravatar",
321                    new I18nizableText("plugin.admin", "PLUGINS_ADMIN_STATISTICS_KERNEL_CONFIG_GRAVATAR_LABEL"),
322                    "ametysicon-body-idcard-black",
323                    configGravatar
324                )
325            ),
326            false
327        );
328    }
329}