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