001/* 002 * Copyright 2015 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.runtime.plugin; 017 018import java.util.ArrayList; 019import java.util.Arrays; 020import java.util.Collection; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.LinkedHashMap; 024import java.util.List; 025import java.util.Map; 026import java.util.stream.Collectors; 027 028import org.apache.avalon.framework.configuration.Configuration; 029import org.apache.commons.lang3.StringUtils; 030 031import org.ametys.runtime.config.ConfigParameterInfo; 032 033/** 034 * A plugin is composed by features, containing components definitions and extensions. 035 */ 036public class Feature 037{ 038 private String _pluginName; 039 private String _featureName; 040 private Configuration _configuration; 041 private boolean _safe; 042 private boolean _passive; 043 private Collection<String> _dependencies = new ArrayList<>(); 044 private Collection<String> _deactivations = new ArrayList<>(); 045 046 private Map<String, ConfigParameterInfo> _configParameters = new LinkedHashMap<>(); 047 private Collection<String> _configParametersRefs = new ArrayList<>(); 048 private Map<String, ConfigParameterInfo> _paramCheckers = new LinkedHashMap<>(); 049 private Map<String, Map<String, ExtensionDefinition>> _extensions = new LinkedHashMap<>(); 050 private Map<String, ComponentDefinition> _components = new LinkedHashMap<>(); 051 052 Feature(String pluginName, String featureName) 053 { 054 _pluginName = pluginName; 055 _featureName = featureName; 056 } 057 058 /** 059 * Returns the declaring plugin name 060 * @return the declaring plugin name 061 */ 062 public String getPluginName() 063 { 064 return _pluginName; 065 } 066 067 /** 068 * Returns this feature name 069 * @return this feature name 070 */ 071 public String getFeatureName() 072 { 073 return _featureName; 074 } 075 076 /** 077 * Returns the feature id, ie. <code>getPluginName() + '/' + getFeatureName()</code> 078 * @return the feature id. 079 */ 080 public String getFeatureId() 081 { 082 return _pluginName + PluginsManager.FEATURE_ID_SEPARATOR + _featureName; 083 } 084 085 /** 086 * Returns true if this feature is passive. 087 * @return true if this feature is passive. 088 */ 089 public boolean isPassive() 090 { 091 return _passive; 092 } 093 094 /** 095 * Returns true if this feature is declared as safe. 096 * @return true if this feature is declared as safe. 097 */ 098 public boolean isSafe() 099 { 100 return _safe; 101 } 102 103 /** 104 * Returns the extensions declared within this feature, grouped by extension point. 105 * @return the extensions declared within this feature, grouped by extension point. 106 */ 107 public Map<String, Collection<String>> getExtensionsIds() 108 { 109 Map<String, Collection<String>> result = new LinkedHashMap<>(); 110 111 for (String point : _extensions.keySet()) 112 { 113 result.put(point, _extensions.get(point).keySet()); 114 } 115 116 return Collections.unmodifiableMap(result); 117 } 118 119 /** 120 * Returns the components declared within this feature, stored by role. 121 * @return the components declared within this feature, stored by role. 122 */ 123 public Map<String, String> getComponentsIds() 124 { 125 Map<String, String> result = new LinkedHashMap<>(); 126 127 for (String role : _components.keySet()) 128 { 129 result.put(role, _components.get(role).getId()); 130 } 131 132 return Collections.unmodifiableMap(result); 133 } 134 135 Configuration getConfiguration() 136 { 137 return _configuration; 138 } 139 140 Collection<String> getDependencies() 141 { 142 return _dependencies; 143 } 144 145 Collection<String> getDeactivations() 146 { 147 return _deactivations; 148 } 149 150 Map<String, Map<String, ExtensionDefinition>> getExtensions() 151 { 152 return _extensions; 153 } 154 155 Map<String, ComponentDefinition> getComponents() 156 { 157 return _components; 158 } 159 160 Map<String, ConfigParameterInfo> getConfigParameters() 161 { 162 return _configParameters; 163 } 164 165 Collection<String> getConfigParametersReferences() 166 { 167 return _configParametersRefs; 168 } 169 170 Map<String, ConfigParameterInfo> getParameterCheckers() 171 { 172 return _paramCheckers; 173 } 174 175 void configure(Configuration configuration) 176 { 177 _configuration = configuration; 178 _passive = configuration.getAttributeAsBoolean("passive", false); 179 _safe = configuration.getAttributeAsBoolean("safe", false); 180 181 _configureDependencies(); 182 _configureDeactivations(); 183 184 _configureExtensions(); 185 _configureComponents(); 186 187 Configuration configConfiguration = configuration.getChild("config"); 188 189 _configureConfigParameters(configConfiguration); 190 _configureConfigParameterReferences(configConfiguration); 191 _configureParametersCheckers(configConfiguration); 192 } 193 194 private void _configureDependencies() 195 { 196 String depends = _configuration.getAttribute("depends", null); 197 198 if (depends != null) 199 { 200 List<String> dependencies = Arrays.stream(StringUtils.split(depends, ',')) 201 .map(String::trim) 202 .filter(StringUtils::isNotEmpty) 203 .collect(Collectors.toList()); 204 205 for (String dependency : dependencies) 206 { 207 String dependingFeatureId = dependency; 208 209 int i = dependency.indexOf('/'); 210 if (i == -1) 211 { 212 dependingFeatureId = _pluginName + PluginsManager.FEATURE_ID_SEPARATOR + dependency; 213 } 214 215 _dependencies.add(dependingFeatureId); 216 } 217 } 218 } 219 220 private void _configureDeactivations() 221 { 222 String deactivates = _configuration.getAttribute("deactivates", null); 223 224 if (deactivates != null) 225 { 226 List<String> deactivations = Arrays.stream(StringUtils.split(deactivates, ',')) 227 .map(String::trim) 228 .filter(StringUtils::isNotEmpty) 229 .collect(Collectors.toList()); 230 231 for (String deactivation : deactivations) 232 { 233 String deactivatedFeatureId = deactivation; 234 235 int i = deactivation.indexOf('/'); 236 if (i == -1) 237 { 238 deactivatedFeatureId = _pluginName + PluginsManager.FEATURE_ID_SEPARATOR + deactivation; 239 } 240 241 _deactivations.add(deactivatedFeatureId); 242 } 243 } 244 } 245 246 private void _configureConfigParameters(Configuration configConfiguration) 247 { 248 Configuration[] parameterConfigurations = configConfiguration.getChildren("param"); 249 for (Configuration parameterConfiguration : parameterConfigurations) 250 { 251 String id = parameterConfiguration.getAttribute("id", null); 252 253 // Add the new parameter to the list of declared parameters 254 _configParameters.put(id, new ConfigParameterInfo(id, _pluginName, parameterConfiguration)); 255 } 256 } 257 258 private void _configureConfigParameterReferences(Configuration configConfiguration) 259 { 260 Configuration[] parameterConfigurations = configConfiguration.getChildren("param-ref"); 261 for (Configuration parameterConfiguration : parameterConfigurations) 262 { 263 String id = parameterConfiguration.getAttribute("id", null); 264 _configParametersRefs.add(id); 265 } 266 } 267 268 private void _configureParametersCheckers(Configuration configConfiguration) 269 { 270 Configuration[] parameterConfigurations = configConfiguration.getChildren("param-checker"); 271 for (Configuration parameterConfiguration : parameterConfigurations) 272 { 273 String id = parameterConfiguration.getAttribute("id", null); 274 275 // Add the new parameter to the list of declared parameters 276 _paramCheckers.put(id, new ConfigParameterInfo(id, _pluginName, parameterConfiguration)); 277 } 278 } 279 280 private void _configureExtensions() 281 { 282 Configuration[] extsConf = _configuration.getChild("extensions").getChildren("extension"); 283 for (Configuration extConf : extsConf) 284 { 285 // XML schema requires attributes id and point and enforces that the combination (id,point) is unique 286 String id = extConf.getAttribute("id", null); 287 String point = extConf.getAttribute("point", null); 288 289 Map<String, ExtensionDefinition> confs = _extensions.get(point); 290 if (confs == null) 291 { 292 confs = new HashMap<>(); 293 _extensions.put(point, confs); 294 } 295 296 confs.put(id, new ExtensionDefinition(id, point, _pluginName, _featureName, extConf)); 297 } 298 } 299 300 private void _configureComponents() 301 { 302 Configuration[] componentsConf = _configuration.getChild("components").getChildren("component"); 303 for (Configuration componentConf : componentsConf) 304 { 305 // XML schema requires attributes id and role 306 String id = componentConf.getAttribute("id", null); 307 String role = componentConf.getAttribute("role", null); 308 309 _components.put(role, new ComponentDefinition(id, role, _pluginName, _featureName, componentConf)); 310 } 311 } 312}