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.web.site; 017 018import java.io.File; 019import java.io.FileInputStream; 020import java.io.FileNotFoundException; 021import java.io.IOException; 022import java.io.InputStream; 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.HashSet; 026import java.util.List; 027import java.util.Map; 028import java.util.Set; 029import java.util.stream.Collectors; 030 031import org.apache.avalon.framework.service.ServiceException; 032import org.apache.avalon.framework.service.ServiceManager; 033import org.apache.cocoon.ProcessingException; 034import org.apache.cocoon.generation.ServiceableGenerator; 035import org.apache.cocoon.xml.AttributesImpl; 036import org.apache.cocoon.xml.XMLUtils; 037import org.apache.excalibur.xml.sax.SAXParser; 038import org.xml.sax.InputSource; 039import org.xml.sax.SAXException; 040 041import org.ametys.core.authentication.CredentialProvider; 042import org.ametys.core.authentication.CredentialProviderFactory; 043import org.ametys.core.authentication.CredentialProviderModel; 044import org.ametys.core.datasource.LDAPDataSourceManager; 045import org.ametys.core.datasource.SQLDataSourceManager; 046import org.ametys.core.user.directory.UserDirectory; 047import org.ametys.core.user.directory.UserDirectoryFactory; 048import org.ametys.core.user.directory.UserDirectoryModel; 049import org.ametys.core.user.population.PopulationContextHelper; 050import org.ametys.core.user.population.UserPopulation; 051import org.ametys.core.user.population.UserPopulationDAO; 052import org.ametys.core.util.IgnoreRootHandler; 053import org.ametys.runtime.config.Config; 054import org.ametys.runtime.parameter.Parameter; 055import org.ametys.runtime.parameter.ParameterHelper.ParameterType; 056import org.ametys.web.repository.site.SiteManager; 057 058/** 059 * Sax the datasources files limited to datasources useful for front-office 060 */ 061public class SitesPopulationsGenerator extends ServiceableGenerator 062{ 063 private SiteManager _siteManager; 064 private PopulationContextHelper _populationContextHelper; 065 private UserPopulationDAO _userPopulationDAO; 066 private UserDirectoryFactory _userDirectoryFactory; 067 private CredentialProviderFactory _credentialProviderFactory; 068 private SQLDataSourceManager _sqlDataSourceManager; 069 private LDAPDataSourceManager _ldapDataSourceManager; 070 private SAXParser _saxParser; 071 072 @Override 073 public void service(ServiceManager smanager) throws ServiceException 074 { 075 super.service(smanager); 076 _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE); 077 _populationContextHelper = (PopulationContextHelper) manager.lookup(PopulationContextHelper.ROLE); 078 _userPopulationDAO = (UserPopulationDAO) manager.lookup(UserPopulationDAO.ROLE); 079 _userDirectoryFactory = (UserDirectoryFactory) manager.lookup(UserDirectoryFactory.ROLE); 080 _credentialProviderFactory = (CredentialProviderFactory) manager.lookup(CredentialProviderFactory.ROLE); 081 _sqlDataSourceManager = (SQLDataSourceManager) manager.lookup(SQLDataSourceManager.ROLE); 082 _ldapDataSourceManager = (LDAPDataSourceManager) manager.lookup(LDAPDataSourceManager.ROLE); 083 _saxParser = (SAXParser) manager.lookup(SAXParser.ROLE); 084 } 085 086 public void generate() throws IOException, SAXException, ProcessingException 087 { 088 contentHandler.startDocument(); 089 XMLUtils.startElement(contentHandler, "Populations"); 090 091 _saxUsedStuff(); 092 _saxPopulationFile(); 093 _saxDatabasesFiles(); 094 _saxMonitoringInfo(); 095 _saxCaptchaInfo(); 096 097 XMLUtils.endElement(contentHandler, "Populations"); 098 contentHandler.endDocument(); 099 } 100 101 private void _saxMonitoringInfo() throws SAXException 102 { 103 boolean enabled = Config.getInstance().getValueAsBoolean("cache.monitoring.schedulers.enable"); 104 105 AttributesImpl attrs = new AttributesImpl(); 106 attrs.addCDATAAttribute("enabled", enabled ? "true" : "false"); 107 XMLUtils.startElement(contentHandler, "Monitoring", attrs); 108 109 if (enabled) 110 { 111 String datasourceId = Config.getInstance().getValueAsString("cache.monitoring.datasource.jdbc.pool"); 112 XMLUtils.createElement(contentHandler, "Datasource", _replaceDefaultIds(datasourceId)); 113 } 114 115 XMLUtils.endElement(contentHandler, "Monitoring"); 116 } 117 118 private void _saxCaptchaInfo() throws SAXException 119 { 120 String type = Config.getInstance().getValueAsString("runtime.captcha.type"); 121 String publicKey = Config.getInstance().getValueAsString("runtime.captcha.recaptcha.publickey"); 122 String secretKey = Config.getInstance().getValueAsString("runtime.captcha.recaptcha.secretkey"); 123 124 AttributesImpl attrs = new AttributesImpl(); 125 attrs.addCDATAAttribute("type", type); 126 attrs.addCDATAAttribute("publicKey", publicKey); 127 attrs.addCDATAAttribute("secretKey", secretKey); 128 129 XMLUtils.createElement(contentHandler, "Captcha", attrs); 130 } 131 132 private void _saxDatabasesFiles() throws IOException, SAXException 133 { 134 _saxSQLDatabaseFile(); 135 136 _saxLDAPDatabaseFile(); 137 } 138 139 private void _saxLDAPDatabaseFile() throws SAXException, IOException 140 { 141 XMLUtils.startElement(contentHandler, "LDAPDatasources"); 142 143 File file = _ldapDataSourceManager.getFileConfiguration(); 144 if (file.exists()) 145 { 146 try (InputStream is = new FileInputStream(file)) 147 { 148 _saxParser.parse(new InputSource(is), new IgnoreRootHandler(contentHandler)); 149 } 150 catch (FileNotFoundException e) 151 { 152 throw new IOException(e); 153 } 154 } 155 156 XMLUtils.endElement(contentHandler, "LDAPDatasources"); 157 } 158 159 private void _saxSQLDatabaseFile() throws SAXException, IOException 160 { 161 XMLUtils.startElement(contentHandler, "SQLDatasources"); 162 163 File file = _sqlDataSourceManager.getFileConfiguration(); 164 if (file.exists()) 165 { 166 try (InputStream is = new FileInputStream(file)) 167 { 168 _saxParser.parse(new InputSource(is), new IgnoreRootHandler(contentHandler)); 169 } 170 catch (FileNotFoundException e) 171 { 172 throw new IOException(e); 173 } 174 } 175 176 XMLUtils.endElement(contentHandler, "SQLDatasources"); 177 } 178 179 private void _saxPopulationFile() throws SAXException, IOException 180 { 181 XMLUtils.startElement(contentHandler, "UserPopulations"); 182 183 try (InputStream is = _userPopulationDAO.getConfigurationFile()) 184 { 185 _saxParser.parse(new InputSource(is), new IgnoreRootHandler(contentHandler)); 186 } 187 188 XMLUtils.endElement(contentHandler, "UserPopulations"); 189 } 190 191 private void _saxUsedStuff() throws SAXException 192 { 193 Set<UserPopulation> usedPopulations = _getPopulationsUsedBySites(); 194 195 XMLUtils.startElement(contentHandler, "InUse"); 196 197 _saxPopulationsInUse(usedPopulations); 198 199 _saxDatasourcesInUse(usedPopulations); 200 201 XMLUtils.endElement(contentHandler, "InUse"); 202 } 203 204 private void _saxDatasourcesInUse(Set<UserPopulation> usedPopulations) throws SAXException 205 { 206 Set<String> usedDatasources = _getDatasourcesUsedByPopulations(usedPopulations); 207 XMLUtils.startElement(contentHandler, "Datasources"); 208 for (String datasourceId : usedDatasources) 209 { 210 XMLUtils.createElement(contentHandler, "Datasource", _replaceDefaultIds(datasourceId)); 211 } 212 XMLUtils.endElement(contentHandler, "Datasources"); 213 } 214 215 private void _saxPopulationsInUse(Set<UserPopulation> usedPopulations) throws SAXException 216 { 217 XMLUtils.startElement(contentHandler, "UserPopulations"); 218 for (UserPopulation userPopulation : usedPopulations) 219 { 220 XMLUtils.createElement(contentHandler, "UserPopulation", userPopulation.getId()); 221 } 222 XMLUtils.endElement(contentHandler, "UserPopulations"); 223 } 224 225 private String _replaceDefaultIds(String datasourceId) 226 { 227 // Default sources won't be default anymore => change it 228 if (_ldapDataSourceManager.getDefaultDataSourceId().equals(datasourceId)) 229 { 230 return _ldapDataSourceManager.getDefaultDataSourceDefinition().getId(); 231 } 232 else if (_sqlDataSourceManager.getDefaultDataSourceId().equals(datasourceId)) 233 { 234 return _sqlDataSourceManager.getDefaultDataSourceDefinition().getId(); 235 } 236 else 237 { 238 return datasourceId; 239 } 240 } 241 242 private Set<UserPopulation> _getPopulationsUsedBySites() 243 { 244 // Retrieve the sites to build the contexts to search on 245 Collection<String> siteNames = _siteManager.getSiteNames(); 246 247 // We return all the populations linked to at least one site 248 List<String> contexts = new ArrayList<>(); 249 for (String siteName : siteNames) 250 { 251 contexts.add("/sites/" + siteName); 252 contexts.add("/sites-fo/" + siteName); 253 } 254 255 Set<String> populations = _populationContextHelper.getUserPopulationsOnContexts(contexts, false, false); 256 return populations.stream().map(_userPopulationDAO::getUserPopulation).collect(Collectors.toSet()); 257 } 258 259 private Set<String> _getDatasourcesUsedByPopulations(Set<UserPopulation> usedPopulations) 260 { 261 Set<String> datasourcesInUse = new HashSet<>(); 262 263 for (UserPopulation userPopulation : usedPopulations) 264 { 265 for (UserDirectory userDirectory : userPopulation.getUserDirectories()) 266 { 267 String userDirectoryModelId = userDirectory.getUserDirectoryModelId(); 268 UserDirectoryModel userDirectoryModel = _userDirectoryFactory.getExtension(userDirectoryModelId); 269 270 Map<String, Object> parameterValues = userDirectory.getParameterValues(); 271 272 Map<String, ? extends Parameter<ParameterType>> userDirectoryModelParameters = userDirectoryModel.getParameters(); 273 for (String userDirectoryModelParameterId : userDirectoryModelParameters.keySet()) 274 { 275 Parameter<ParameterType> userDirectoryModelParameter = userDirectoryModelParameters.get(userDirectoryModelParameterId); 276 if (ParameterType.DATASOURCE.equals(userDirectoryModelParameter.getType())) 277 { 278 String datasourceId = (String) parameterValues.get(userDirectoryModelParameterId); 279 datasourcesInUse.add(datasourceId); 280 } 281 } 282 } 283 284 for (CredentialProvider credentialProvider : userPopulation.getCredentialProviders()) 285 { 286 String credentialProviderModelId = credentialProvider.getCredentialProviderModelId(); 287 CredentialProviderModel credentialProviderModel = _credentialProviderFactory.getExtension(credentialProviderModelId); 288 289 Map<String, Object> parameterValues = credentialProvider.getParameterValues(); 290 291 Map<String, ? extends Parameter<ParameterType>> credentialProviderModelParameters = credentialProviderModel.getParameters(); 292 for (String credentialProviderParameterId : credentialProviderModelParameters.keySet()) 293 { 294 Parameter<ParameterType> credentialProviderModelParameter = credentialProviderModelParameters.get(credentialProviderParameterId); 295 if (ParameterType.DATASOURCE.equals(credentialProviderModelParameter.getType())) 296 { 297 String datasourceId = (String) parameterValues.get(credentialProviderParameterId); 298 datasourcesInUse.add(datasourceId); 299 } 300 } 301 } 302 } 303 304 return datasourcesInUse; 305 } 306}