001/*
002 *  Copyright 2010 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.Collections;
019import java.util.LinkedHashMap;
020import java.util.Map;
021import java.util.Set;
022import java.util.regex.Pattern;
023
024import org.apache.avalon.framework.configuration.Configuration;
025import org.apache.avalon.framework.configuration.ConfigurationException;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028
029import org.ametys.runtime.model.Enumerator;
030import org.ametys.runtime.model.disableconditions.DisableConditions;
031import org.ametys.runtime.parameter.Validator;
032import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint;
033import org.ametys.runtime.plugin.component.ThreadSafeComponentManager;
034import org.ametys.web.data.type.ModelItemTypeExtensionPoint;
035
036/**
037 * Extension point holding all {@link SiteParameterWrapper} definitions.
038 */
039public class SiteConfigurationExtensionPoint extends AbstractThreadSafeComponentExtensionPoint<SiteParameterWrapper>
040{
041    /** Avalon Role */
042    public static final String ROLE = SiteConfigurationExtensionPoint.class.getName();
043    
044    private static final Pattern __PARAM_NAME_PATTERN = Pattern.compile("[a-z][a-z0-9-_]*", Pattern.CASE_INSENSITIVE);
045    
046    /** Parameter's wrappers map, indexed by parameter ID. */
047    private Map<String, SiteParameterWrapper> _parameterWrappers;
048    
049    /** ComponentManager for {@link DisableConditions}. */
050    private ThreadSafeComponentManager<DisableConditions> _disableConditionsManager;
051    
052    /** ComponentManager for {@link Validator}s. */
053    private ThreadSafeComponentManager<Validator> _validatorManager;
054    
055    /** ComponentManager for {@link Enumerator}s. */
056    private ThreadSafeComponentManager<Enumerator> _enumeratorManager;
057    
058    /** Parser of parameter's wrappers */
059    private SiteParameterWrapperParser _parameterWrapperParser;
060    
061    /** Site parameter parser. */
062    private SiteParameterParser _parameterParser;
063    
064    private ModelItemTypeExtensionPoint _siteParameterTypeEP;
065
066    
067    @Override
068    public void initialize() throws Exception
069    {
070        super.initialize();
071
072        _parameterWrappers = new LinkedHashMap<>();
073        
074        _disableConditionsManager = new ThreadSafeComponentManager<>();
075        _disableConditionsManager.setLogger(getLogger());
076        _disableConditionsManager.contextualize(_context);
077        _disableConditionsManager.service(_cocoonManager);
078        
079        _validatorManager = new ThreadSafeComponentManager<>();
080        _validatorManager.setLogger(getLogger());
081        _validatorManager.contextualize(_context);
082        _validatorManager.service(_cocoonManager);
083        
084        _enumeratorManager = new ThreadSafeComponentManager<>();
085        _enumeratorManager.setLogger(getLogger());
086        _enumeratorManager.contextualize(_context);
087        _enumeratorManager.service(_cocoonManager);
088        
089        _parameterParser = new SiteParameterParser(_siteParameterTypeEP, _disableConditionsManager, _enumeratorManager, _validatorManager);
090        _parameterWrapperParser = new SiteParameterWrapperParser(_parameterParser);
091    }
092    
093    @Override
094    public void service(ServiceManager manager) throws ServiceException
095    {
096        super.service(manager);
097        _siteParameterTypeEP = (ModelItemTypeExtensionPoint) manager.lookup(ModelItemTypeExtensionPoint.ROLE_SITE_PARAM);
098    }
099    
100    /**
101     * Dispose the manager before restarting it
102     */
103    @Override
104    public void dispose()
105    {
106        _parameterWrapperParser = null;
107        _parameterParser = null;
108        
109        _parameterWrappers = null;
110        _disableConditionsManager.dispose();
111        _disableConditionsManager = null;
112        _validatorManager.dispose();
113        _validatorManager = null;
114        _enumeratorManager.dispose();
115        _enumeratorManager = null;
116        
117        super.dispose();
118    }
119    
120    @Override
121    public boolean hasExtension(String id)
122    {
123        return _parameterWrappers.containsKey(id);
124    }
125    
126    @Override
127    public void addExtension(String id, String pluginName, String featureName, Configuration configuration) throws ConfigurationException
128    {
129        if (getLogger().isDebugEnabled())
130        {
131            getLogger().debug("Adding site parameters from feature " + pluginName + "/" + featureName);
132        }
133        
134        Configuration[] parameterConfigurations = configuration.getChildren("param");
135        for (Configuration parameterConfiguration : parameterConfigurations)
136        {
137            _addParameter(pluginName, featureName, parameterConfiguration);
138        }
139    }
140    
141    /**
142     * Declare a site parameter.
143     * @param pluginName The name of the plugin declaring the extension.
144     * @param featureName the name of the feature
145     * @param configuration The parameter configuration.
146     * @throws ConfigurationException if configuration is not complete.
147     */
148    protected void _addParameter(String pluginName, String featureName, Configuration configuration) throws ConfigurationException
149    {
150        SiteParameterWrapper parameter = _parameterWrapperParser.parse(_cocoonManager, pluginName, configuration);
151        
152        String name = parameter.getDefinition().getName();
153        
154        if (!__PARAM_NAME_PATTERN.matcher(name).matches())
155        {
156            throw new ConfigurationException("The feature " + pluginName + "/" + featureName + " declared an invalid site parameter name '" + name + "'. This value is not permited: only [a-zA-Z][a-zA-Z0-9-_]* are allowed.", configuration);
157        }
158        
159        if (_parameterWrappers.containsKey(name))
160        {
161            throw new ConfigurationException("In feature " + pluginName + "/" + featureName + " the parameter '" + name + "' is already declared. Parameter ids must be unique.", configuration);
162        }
163        
164        _parameterWrappers.put(name, parameter);
165        
166        if (getLogger().isDebugEnabled())
167        {
168            getLogger().debug("Site parameter added: " + name);
169        }
170    }
171    
172    @Override
173    public SiteParameterWrapper getExtension(String id)
174    {
175        if (hasExtension(id))
176        {
177            return _parameterWrappers.get(id);
178        }
179        else
180        {
181            throw new IllegalArgumentException("There is no site parameter named '" + id + "'.");
182        }
183    }
184    
185    @Override
186    public Set<String> getExtensionsIds()
187    {
188        return Collections.unmodifiableSet(_parameterWrappers.keySet());
189    }
190    
191    @Override
192    public void initializeExtensions() throws Exception
193    {
194        super.initializeExtensions();
195        _parameterParser.lookupComponents();
196    }
197}