001/* 002 * Copyright 2019 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.util.Collection; 019import java.util.HashMap; 020import java.util.Iterator; 021import java.util.Map; 022 023import org.apache.avalon.framework.activity.Disposable; 024import org.apache.avalon.framework.activity.Initializable; 025import org.apache.avalon.framework.component.Component; 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.avalon.framework.service.Serviceable; 029 030import org.ametys.plugins.repository.UnknownAmetysObjectException; 031import org.ametys.runtime.i18n.I18nizableText; 032import org.ametys.runtime.model.ElementDefinition; 033import org.ametys.runtime.model.ModelHelper; 034import org.ametys.runtime.model.View; 035import org.ametys.runtime.model.disableconditions.DefaultDisableConditionsEvaluator; 036import org.ametys.runtime.model.disableconditions.DisableConditionsEvaluator; 037import org.ametys.runtime.model.exception.UndefinedItemPathException; 038import org.ametys.runtime.parameter.ValidationResult; 039import org.ametys.runtime.plugin.component.AbstractLogEnabled; 040import org.ametys.web.repository.site.Site; 041import org.ametys.web.repository.site.SiteManager; 042import org.ametys.web.repository.site.SiteType; 043import org.ametys.web.repository.site.SiteTypesExtensionPoint; 044 045/** 046 * Helper component for managing sites configuration. 047 */ 048public class SiteConfigurationManager extends AbstractLogEnabled implements Component, Serviceable, Initializable, Disposable 049{ 050 /** Avalon Role */ 051 public static final String ROLE = SiteConfigurationManager.class.getName(); 052 053 /** The site manager. */ 054 protected SiteManager _siteManager; 055 /** The site type extension point. */ 056 protected SiteTypesExtensionPoint _siteTypesExtensionPoint; 057 /** The disable conditions evaluator */ 058 protected DisableConditionsEvaluator _disableConditionsEvaluator; 059 060 /** Determines if all parameters are valued, by site. */ 061 protected Map<String, Boolean> _areSiteComplete; 062 063 public void service(ServiceManager manager) throws ServiceException 064 { 065 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 066 _siteTypesExtensionPoint = (SiteTypesExtensionPoint) manager.lookup(SiteTypesExtensionPoint.ROLE); 067 _disableConditionsEvaluator = (DisableConditionsEvaluator) manager.lookup(DefaultDisableConditionsEvaluator.ROLE); 068 } 069 070 public void initialize() throws Exception 071 { 072 _areSiteComplete = new HashMap<>(); 073 } 074 075 public void dispose() 076 { 077 _areSiteComplete = new HashMap<>(); 078 } 079 080 /** 081 * Reload a site's configuration. 082 * @param siteName the site name. 083 * @throws UnknownAmetysObjectException if the site doesn't exist. 084 */ 085 public void reloadSiteConfiguration(String siteName) throws UnknownAmetysObjectException 086 { 087 // Check if the site exists. 088 Site site = _siteManager.getSite(siteName); 089 090 // Reload the site configuration. 091 reloadSiteConfiguration(site); 092 } 093 094 /** 095 * Reload a site's configuration. 096 * @param site the site. 097 * @throws UnknownAmetysObjectException if the site doesn't exist. 098 */ 099 public void reloadSiteConfiguration(Site site) throws UnknownAmetysObjectException 100 { 101 // Reload the site configuration. 102 _areSiteComplete.put(site.getName(), _isSiteConfigurationValid(site)); 103 } 104 105 /** 106 * Remove a site's configuration. 107 * @param site the site. 108 */ 109 public void removeSiteConfiguration(Site site) 110 { 111 removeSiteConfiguration(site.getName()); 112 } 113 114 /** 115 * Remove a site's configuration. 116 * @param siteName the site name. 117 */ 118 public void removeSiteConfiguration(String siteName) 119 { 120 if (_areSiteComplete.containsKey(siteName)) 121 { 122 _areSiteComplete.remove(siteName); 123 } 124 } 125 126 /** 127 * Validate the configuration of the given site. 128 * @param siteName the name of the site to check. 129 * @return <code>true</code> if the site is correctly configured, <code>false</code> otherwise. 130 * @throws UnknownAmetysObjectException if the site doesn't exist. 131 */ 132 public boolean isSiteConfigurationValid(String siteName) throws UnknownAmetysObjectException 133 { 134 if (siteName == null) 135 { 136 throw new IllegalArgumentException("Cannot determine if a null siteName is valid or not"); 137 } 138 139 // Check if the site exists. 140 if (!_siteManager.hasSite(siteName)) 141 { 142 throw new UnknownAmetysObjectException ("Unknown site '" + siteName + "'. Can not check configuration."); 143 } 144 145 // Validate the site configuration now if it's not already done. 146 Site site = _siteManager.getSite(siteName); 147 return isSiteConfigurationValid(site); 148 } 149 150 /** 151 * Validate the configuration of the given site. 152 * @param site the site to check. 153 * @return <code>true</code> if the site is correctly configured, <code>false</code> otherwise. 154 * @throws UnknownAmetysObjectException if the site doesn't exist. 155 */ 156 public boolean isSiteConfigurationValid(Site site) throws UnknownAmetysObjectException 157 { 158 if (site == null) 159 { 160 throw new IllegalArgumentException("Cannot determine if a null site is valid or not"); 161 } 162 163 // Validate the site configuration now if it's not already done. 164 if (!_areSiteComplete.containsKey(site.getName())) 165 { 166 _areSiteComplete.put(site.getName(), _isSiteConfigurationValid(site)); 167 } 168 169 return _areSiteComplete.get(site.getName()); 170 } 171 172 /** 173 * Validate the configuration of the given site. 174 * @param site the site to check. 175 * @return <code>true</code> if the site is correctly configured, <code>false</code> otherwise. 176 */ 177 protected boolean _isSiteConfigurationValid(Site site) 178 { 179 if (getLogger().isDebugEnabled()) 180 { 181 getLogger().debug("Validating the configuration of site '" + site + "'"); 182 } 183 184 SiteType siteType = _siteTypesExtensionPoint.getExtension(site.getType()); 185 if (siteType == null) 186 { 187 getLogger().error("Site " + site.getName() + " has the unknown type '" + site.getType() + "'"); 188 return false; 189 } 190 191 boolean areParametersValid = true; 192 193 Iterator<ElementDefinition> definitionsIterator = siteType.getModelItems().iterator(); 194 while (definitionsIterator.hasNext() && areParametersValid) 195 { 196 ElementDefinition item = definitionsIterator.next(); 197 boolean isDisabled = _disableConditionsEvaluator.evaluateDisableConditions(item, item.getPath(), site); 198 if (!isDisabled) 199 { 200 areParametersValid = _isValidSiteParameter(item, site); 201 } 202 } 203 204 return areParametersValid; 205 } 206 207 /** 208 * Validate the the given site parameter 209 * @param parameter the site parameter to validate. 210 * @param site the site 211 * @return true if the parameter's value is valid, false otherwise. 212 */ 213 protected boolean _isValidSiteParameter(ElementDefinition parameter, Site site) 214 { 215 // TODO RUNTIME-2897: call the validateValue without boolean when multiple values are managed in enumerators 216 Object value = site.getValue(parameter.getName(), true, null); 217 ValidationResult validationResult = ModelHelper.validateValue(parameter, value, false); 218 if (validationResult.hasErrors()) 219 { 220 if (getLogger().isWarnEnabled()) 221 { 222 StringBuffer sb = new StringBuffer(); 223 224 sb.append("The parameter '") 225 .append(parameter.getPath()) 226 .append("' of site '") 227 .append(site.getName()) 228 .append("' is not valid"); 229 if (site.hasValue(parameter.getName())) 230 { 231 sb.append(" with value '"); 232 try 233 { 234 sb.append(parameter.getType().toString(value)); 235 } 236 catch (Exception e) 237 { 238 sb.append(value.toString()); 239 } 240 sb.append("'"); 241 } 242 else 243 { 244 sb.append(" with empty value"); 245 } 246 sb.append(":"); 247 248 for (I18nizableText error : validationResult.getErrors()) 249 { 250 sb.append("\n* " + error.toString()); 251 } 252 253 sb.append("\nConfiguration is not initialized"); 254 255 getLogger().warn(sb.toString()); 256 } 257 258 return false; 259 } 260 261 return true; 262 } 263 264 /** 265 * Retrieves the parameters of the given site 266 * @param siteName the name of the site 267 * @return the site's parameters 268 */ 269 public Collection<ElementDefinition> getSiteParameters(String siteName) 270 { 271 Site site = _siteManager.getSite(siteName); 272 return getSiteParameters(site); 273 } 274 275 /** 276 * Retrieves the parameters of the given site 277 * @param site the site 278 * @return the site's parameters 279 */ 280 public Collection<ElementDefinition> getSiteParameters(Site site) 281 { 282 SiteType siteType = _siteTypesExtensionPoint.getExtension(site.getType()); 283 return siteType.getModelItems(); 284 } 285 286 /** 287 * Retrieves the parameter of the given site with the given name 288 * @param siteName the name of the site 289 * @param parameterName the name of the parameter to retrieve 290 * @return the site's parameter 291 * @throws UndefinedItemPathException if there is no site parameter defined with the given name 292 */ 293 public ElementDefinition getSiteParameter(String siteName, String parameterName) throws UndefinedItemPathException 294 { 295 Site site = _siteManager.getSite(siteName); 296 return getSiteParameter(site, parameterName); 297 } 298 299 /** 300 * Retrieves the parameter of the given site with the given name 301 * @param site the site 302 * @param parameterName the name of the parameter to retrieve 303 * @return the site's parameter 304 * @throws UndefinedItemPathException if there is no site parameter defined with the given name 305 */ 306 public ElementDefinition getSiteParameter(Site site, String parameterName) throws UndefinedItemPathException 307 { 308 SiteType siteType = _siteTypesExtensionPoint.getExtension(site.getType()); 309 return siteType.getModelItem(parameterName); 310 } 311 312 /** 313 * Retrieves the view of the site with the given name 314 * @param siteName the name of the site 315 * @return the site's view 316 */ 317 public View getSiteView(String siteName) 318 { 319 Site site = _siteManager.getSite(siteName); 320 return getSiteView(site); 321 } 322 323 /** 324 * Retrieves the view of the site with the given name 325 * @param site the site 326 * @return the site's view 327 */ 328 public View getSiteView(Site site) 329 { 330 SiteType siteType = _siteTypesExtensionPoint.getExtension(site.getType()); 331 return siteType.getView(); 332 } 333}