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.plugins.contentio.synchronize.impl; 017 018import java.util.Collection; 019import java.util.LinkedHashMap; 020import java.util.Map; 021 022import org.apache.avalon.framework.activity.Disposable; 023import org.apache.avalon.framework.configuration.Configurable; 024import org.apache.avalon.framework.configuration.Configuration; 025import org.apache.avalon.framework.configuration.ConfigurationException; 026import org.apache.avalon.framework.context.Context; 027import org.apache.avalon.framework.context.ContextException; 028import org.apache.avalon.framework.context.Contextualizable; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.avalon.framework.service.Serviceable; 032 033import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollection; 034import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollectionModel; 035import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollectionModelParameterParser; 036import org.ametys.runtime.i18n.I18nizableText; 037import org.ametys.runtime.model.Enumerator; 038import org.ametys.runtime.model.ModelItem; 039import org.ametys.runtime.model.disableconditions.DisableConditions; 040import org.ametys.runtime.model.type.ModelItemTypeExtensionPoint; 041import org.ametys.runtime.parameter.Validator; 042import org.ametys.runtime.plugin.component.AbstractLogEnabled; 043import org.ametys.runtime.plugin.component.PluginAware; 044import org.ametys.runtime.plugin.component.ThreadSafeComponentManager; 045 046/** 047 * Implementation of {@link SynchronizableContentsCollectionModel} able to populate contents from a LDAP source 048 * 049 */ 050public class DefaultSynchronizableContentsCollectionModel extends AbstractLogEnabled implements SynchronizableContentsCollectionModel, Serviceable, Contextualizable, PluginAware, Configurable, Disposable 051{ 052 private ModelItemTypeExtensionPoint _sccParameterTypeExtensionPoint; 053 private ServiceManager _manager; 054 private Context _context; 055 056 // ComponentManager for disable conditions 057 private ThreadSafeComponentManager<DisableConditions> _disableConditionsManager; 058 059 // ComponentManager for validators 060 private ThreadSafeComponentManager<Validator> _validatorManager; 061 062 // ComponentManager for enumerators 063 private ThreadSafeComponentManager<Enumerator> _enumeratorManager; 064 065 private String _id; 066 private Class<SynchronizableContentsCollection> _syncCollectionClass; 067 private I18nizableText _label; 068 private I18nizableText _description; 069 private Map<String, ModelItem> _parameters = new LinkedHashMap<>(); 070 private String _pluginName; 071 072 public void service(ServiceManager manager) throws ServiceException 073 { 074 _manager = manager; 075 _sccParameterTypeExtensionPoint = (ModelItemTypeExtensionPoint) manager.lookup(ModelItemTypeExtensionPoint.ROLE_CONFIG); 076 } 077 078 public void contextualize(Context context) throws ContextException 079 { 080 _context = context; 081 } 082 083 @Override 084 public void setPluginInfo(String pluginName, String featureName, String id) 085 { 086 _pluginName = pluginName; 087 _id = id; 088 } 089 090 @SuppressWarnings("unchecked") 091 public void configure(Configuration configuration) throws ConfigurationException 092 { 093 _label = I18nizableText.parseI18nizableText(configuration.getChild("label"), "plugin." + _pluginName); 094 _description = I18nizableText.parseI18nizableText(configuration.getChild("description"), "plugin." + _pluginName); 095 096 String className = null; 097 try 098 { 099 className = configuration.getChild("class").getAttribute("name"); 100 _syncCollectionClass = (Class<SynchronizableContentsCollection>) Class.forName(className); 101 } 102 catch (ClassNotFoundException | ConfigurationException e) 103 { 104 throw new ConfigurationException("SynchronizableContentsCollection model with id '" + _id + "' has an invalid configuration for class name " + (className != null ? className + " <class not found>" : "<missing tag <class>") + "'", e); 105 } 106 107 if (!SynchronizableContentsCollection.class.isAssignableFrom(_syncCollectionClass)) 108 { 109 throw new ConfigurationException("SynchronizableContentsCollection model with id '" + _id + "' has an invalid configuration: '" + className + "' is not an instance of SynchronizableContentsCollection"); 110 } 111 112 configureParameters(configuration); 113 } 114 115 /** 116 * Configure the SCC parameters 117 * @param configuration the model configuration 118 * @throws ConfigurationException if a configuration exception occurred 119 */ 120 protected void configureParameters(Configuration configuration) throws ConfigurationException 121 { 122 _disableConditionsManager = new ThreadSafeComponentManager<>(); 123 _disableConditionsManager.setLogger(getLogger()); 124 _disableConditionsManager.contextualize(_context); 125 _disableConditionsManager.service(_manager); 126 127 _validatorManager = new ThreadSafeComponentManager<>(); 128 _validatorManager.setLogger(getLogger()); 129 _validatorManager.contextualize(_context); 130 _validatorManager.service(_manager); 131 132 _enumeratorManager = new ThreadSafeComponentManager<>(); 133 _enumeratorManager.setLogger(getLogger()); 134 _enumeratorManager.contextualize(_context); 135 _enumeratorManager.service(_manager); 136 137 SynchronizableContentsCollectionModelParameterParser sccParametersParser = new SynchronizableContentsCollectionModelParameterParser(_sccParameterTypeExtensionPoint, _disableConditionsManager, _enumeratorManager, _validatorManager); 138 139 Configuration parametersConfiguration = configuration.getChild("parameters"); 140 Configuration[] paramsConfiguration = parametersConfiguration.getChildren("param"); 141 for (Configuration paramConfiguration : paramsConfiguration) 142 { 143 ModelItem parameter = sccParametersParser.parse(_manager, _pluginName, "plugin." + _pluginName, paramConfiguration, this, null); 144 String parameterPath = parameter.getPath(); 145 146 if (_parameters.containsKey(parameterPath)) 147 { 148 throw new ConfigurationException("The parameter '" + parameterPath + "' is already declared. IDs must be unique.", paramConfiguration); 149 } 150 151 _parameters.put(parameterPath, parameter); 152 } 153 154 try 155 { 156 sccParametersParser.lookupComponents(); 157 } 158 catch (Exception e) 159 { 160 throw new ConfigurationException("Unable to lookup parameter local components", configuration, e); 161 } 162 } 163 164 @Override 165 public void dispose() 166 { 167 _disableConditionsManager.dispose(); 168 _disableConditionsManager = null; 169 170 _validatorManager.dispose(); 171 _validatorManager = null; 172 173 _enumeratorManager.dispose(); 174 _enumeratorManager = null; 175 } 176 177 @Override 178 public String getId() 179 { 180 return _id; 181 } 182 183 @Override 184 public I18nizableText getLabel() 185 { 186 return _label; 187 } 188 189 @Override 190 public I18nizableText getDescription() 191 { 192 return _description; 193 } 194 195 @Override 196 public Collection<ModelItem> getModelItems() 197 { 198 return _parameters.values(); 199 } 200 201 @Override 202 public String getPluginName() 203 { 204 return _pluginName; 205 } 206 207 @Override 208 public Class<SynchronizableContentsCollection> getSynchronizableCollectionClass() 209 { 210 return _syncCollectionClass; 211 } 212}