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