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.cms.search.model; 017 018import java.util.ArrayList; 019import java.util.Collections; 020import java.util.List; 021 022import org.apache.avalon.framework.component.ComponentException; 023import org.apache.avalon.framework.configuration.Configuration; 024import org.apache.avalon.framework.configuration.ConfigurationException; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.commons.lang3.StringUtils; 028 029import org.ametys.cms.data.type.ModelItemTypeExtensionPoint; 030import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint; 031 032/** 033 * Extension point handling {@link SystemProperty} objects. 034 */ 035public class SystemPropertyExtensionPoint extends AbstractThreadSafeComponentExtensionPoint<SystemProperty>// implements Initializable 036{ 037 /** The extension point role. */ 038 public static final String ROLE = SystemPropertyExtensionPoint.class.getName(); 039 040 /** Content properties types extension point */ 041 protected ModelItemTypeExtensionPoint _contentPropertyTypeExtensionPoint; 042 043 /** Collection of the displayable properties. */ 044 protected List<String> _displayProps; 045 046 /** Collection of the searchable properties. */ 047 protected List<String> _searchProps; 048 049 @Override 050 public void service(ServiceManager manager) throws ServiceException 051 { 052 super.service(manager); 053 _contentPropertyTypeExtensionPoint = (ModelItemTypeExtensionPoint) manager.lookup(ModelItemTypeExtensionPoint.ROLE_CONTENT_PROPERTY); 054 } 055 056 @Override 057 public void addExtension(String id, String pluginName, String featureName, Configuration configuration) throws ConfigurationException 058 { 059 if (getLogger().isDebugEnabled()) 060 { 061 getLogger().debug("Adding system properties from feature " + pluginName + "/" + featureName); 062 } 063 064 try 065 { 066 for (Configuration propConf : configuration.getChildren("property")) 067 { 068 addSystemProperty(pluginName, featureName, propConf); 069 } 070 } 071 catch (ConfigurationException e) 072 { 073 if (getLogger().isWarnEnabled()) 074 { 075 getLogger().warn("The feature '" + pluginName + "/" + featureName + "' declares a system property extension with an invalid configuration.", e); 076 } 077 } 078 } 079 080 /** 081 * Declare a new system property. 082 * @param pluginName The name of the plugin declaring the extension 083 * @param featureName The feature name. 084 * @param configuration The configuration of the extension 085 * @throws ConfigurationException if configuration if not complete 086 */ 087 @SuppressWarnings("unchecked") 088 protected void addSystemProperty(String pluginName, String featureName, Configuration configuration) throws ConfigurationException 089 { 090 String id = configuration.getAttribute("id", ""); 091 if (StringUtils.isBlank(id)) 092 { 093 throw new ConfigurationException("SystemProperty declaration is incorrect since no 'id' attribute is specified (or may be empty)", configuration); 094 } 095 096 String className = configuration.getAttribute("class", ""); 097 if (StringUtils.isBlank(className)) 098 { 099 throw new ConfigurationException("SystemProperty declaration is incorrect since no 'class' attribute is specified (or may be empty)", configuration); 100 } 101 102 try 103 { 104 Class<?> clazz = Class.forName(className); 105 if (!SystemProperty.class.isAssignableFrom(clazz)) 106 { 107 throw new ConfigurationException("The system property declaration must be declared with a class implementing SystemProperty."); 108 } 109 110 addComponent(pluginName, featureName, id, (Class<? extends SystemProperty>) clazz, configuration); 111 } 112 catch (ComponentException | ClassNotFoundException e) 113 { 114 throw new ConfigurationException("Unable to instanciate the SystemProperty of id '" + id + "'.", e); 115 } 116 } 117 118 @SuppressWarnings("unchecked") 119 @Override 120 public void initializeExtensions() throws Exception 121 { 122 super.initializeExtensions(); 123 124 _displayProps = new ArrayList<>(); 125 _searchProps = new ArrayList<>(); 126 127 for (String id : getExtensionsIds()) 128 { 129 SystemProperty prop = getExtension(id); 130 prop.setAvailableTypeExtensionPoint(_contentPropertyTypeExtensionPoint); 131 132 if (prop.isDisplayable()) 133 { 134 _displayProps.add(id); 135 } 136 if (prop.isSearchable()) 137 { 138 _searchProps.add(id); 139 } 140 } 141 } 142 143 /** 144 * Get the IDs of the properties that can be displayed. 145 * @return The Collection of properties that can be displayed. 146 */ 147 public List<String> getDisplayProperties() 148 { 149 return Collections.unmodifiableList(_displayProps); 150 } 151 152 /** 153 * Get the IDs of the properties that can be searched on. 154 * @return The Collection of properties that can be searched on. 155 */ 156 public List<String> getSearchProperties() 157 { 158 return Collections.unmodifiableList(_searchProps); 159 } 160 161 /** 162 * Tests if a property exists and is displayable. 163 * @param name The property name. 164 * @return <code>true</code> if the property exists and is displayable. 165 */ 166 public boolean isDisplayable(String name) 167 { 168 return _displayProps.contains(name); 169 } 170 171 /** 172 * Tests if a property exists and is searchable. 173 * @param name The property name. 174 * @return <code>true</code> if the property exists and is searchable. 175 */ 176 public boolean isSearchable(String name) 177 { 178 return _searchProps.contains(name); 179 } 180 181}