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