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.plugins.contentstree; 017 018import java.io.InputStream; 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.HashSet; 022import java.util.Set; 023 024import org.apache.avalon.framework.configuration.Configurable; 025import org.apache.avalon.framework.configuration.Configuration; 026import org.apache.avalon.framework.configuration.ConfigurationException; 027import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031import org.apache.commons.lang3.StringUtils; 032import org.apache.excalibur.source.Source; 033import org.apache.excalibur.source.SourceResolver; 034import org.apache.tika.io.IOUtils; 035 036import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 037import org.ametys.runtime.plugin.component.PluginAware; 038 039/** 040 * Static implementation based on configuration. See doc for template. 041 */ 042public class StaticTreeConfiguration implements TreeConfiguration, Configurable, Serviceable, PluginAware 043{ 044 /** The ui tool role */ 045 protected String _uiToolRole; 046 /** The collection of elements */ 047 protected Set<TreeConfigurationElements> _elements; 048 /** The content type extension point */ 049 protected ContentTypeExtensionPoint _contentTypesEP; 050 /** The excalibur source resolver */ 051 protected SourceResolver _sourceResolver; 052 /** The plugin name */ 053 protected String _pluginName; 054 /** The extension id */ 055 protected String _id; 056 057 private Configuration _configuration; 058 059 @Override 060 public String getId() 061 { 062 return _id; 063 } 064 065 @Override 066 public void setPluginInfo(String pluginName, String featureName, String id) 067 { 068 _pluginName = pluginName; 069 } 070 071 @Override 072 public void service(ServiceManager manager) throws ServiceException 073 { 074 _contentTypesEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 075 _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); 076 } 077 078 @Override 079 public void configure(Configuration initialConfiguration) throws ConfigurationException 080 { 081 _id = initialConfiguration.getAttribute("id"); 082 083 _configuration = _getDeportedConfiguration(initialConfiguration); 084 } 085 086 private void _lazyConfigure() 087 { 088 if (_configuration != null) 089 { 090 try 091 { 092 _uiToolRole = _configuration.getAttribute("id"); 093 _elements = new HashSet<>(); 094 095 for (Configuration contentTypeConfiguration : _configuration.getChild("elements").getChildren("content-type")) 096 { 097 Collection<TreeConfigurationContentType> contentTypesInfo = getContentTypesInfos(contentTypeConfiguration.getChild("ids")); 098 Collection<TreeConfigurationElementsChild> childNodes = getChildNodes(contentTypeConfiguration.getChild("children")); 099 100 TreeConfigurationElements element = new TreeConfigurationElements(contentTypesInfo, childNodes); 101 _elements.add(element); 102 } 103 104 _configuration = null; 105 } 106 catch (ConfigurationException e) 107 { 108 throw new IllegalStateException("An error occured while configuring tree '" + _id + "'", e); 109 } 110 } 111 } 112 113 private Configuration _getDeportedConfiguration(Configuration initialConfiguration) throws ConfigurationException 114 { 115 String treeConfigURL = initialConfiguration.getChild("tree-config").getValue(); 116 Source treeConfigSource = null; 117 InputStream is = null; 118 try 119 { 120 treeConfigSource = _sourceResolver.resolveURI(treeConfigURL, "plugin:" + _pluginName + "://", null); 121 is = treeConfigSource.getInputStream(); 122 return new DefaultConfigurationBuilder().build(is); 123 } 124 catch (Exception e) 125 { 126 throw new ConfigurationException("Cannot open the file '" + treeConfigURL + "'", initialConfiguration, e); 127 } 128 finally 129 { 130 IOUtils.closeQuietly(is); 131 _sourceResolver.release(treeConfigSource); 132 } 133 } 134 135 /** 136 * Get the child nodes 137 * @param configuration The configuration 138 * @return the child nodes 139 * @throws ConfigurationException if configuration is invalid 140 */ 141 protected Collection<TreeConfigurationElementsChild> getChildNodes(Configuration configuration) throws ConfigurationException 142 { 143 Collection<TreeConfigurationElementsChild> childnodes = new ArrayList<>(); 144 145 for (Configuration childConfiguration : configuration.getChildren()) 146 { 147 if (StringUtils.equals(childConfiguration.getName(), "metadata")) 148 { 149 String id = childConfiguration.getAttribute("id"); 150 151 TreeConfigurationElementsChild child = new MetadataTreeConfigurationElementsChild(id); 152 childnodes.add(child); 153 } 154 else 155 { 156 throw new ConfigurationException("Unknown child of type '" + childConfiguration.getName() + "'", childConfiguration); 157 } 158 } 159 160 return childnodes; 161 } 162 163 /** 164 * Get the contents infos using a configuration 165 * @param configuration the configuration 166 * @return the contents infos using a configuration 167 * @throws ConfigurationException if an error occurred 168 */ 169 protected Collection<TreeConfigurationContentType> getContentTypesInfos(Configuration configuration) throws ConfigurationException 170 { 171 Collection<TreeConfigurationContentType> contentTypesInfo = new ArrayList<>(); 172 173 boolean elementsCanBeRoot = configuration.getAttributeAsBoolean("can-be-root", false); 174 boolean elementsInherit = configuration.getAttributeAsBoolean("inherit", false); 175 String elementsBusMessageType = configuration.getAttribute("bus-message-type", "content"); 176 177 for (Configuration idConfiguration : configuration.getChildren("id")) 178 { 179 TreeConfigurationContentType contentTypeInfo = getContentTypeInfo(idConfiguration, elementsCanBeRoot, elementsInherit, elementsBusMessageType); 180 contentTypesInfo.add(contentTypeInfo); 181 } 182 183 return contentTypesInfo; 184 } 185 186 /** 187 * Get the content info using a configuration 188 * @param configuration The configuration 189 * @param defaultCanBeRoot default value for root property 190 * @param defaultInherit default value for inherit property 191 * @param defaultBusMessageType default type of message 192 * @return the content info using a configuration 193 * @throws ConfigurationException if the configuration is invalid 194 */ 195 protected TreeConfigurationContentType getContentTypeInfo(Configuration configuration, boolean defaultCanBeRoot, boolean defaultInherit, String defaultBusMessageType) throws ConfigurationException 196 { 197 boolean canBeRoot = configuration.getAttributeAsBoolean("can-be-root", defaultCanBeRoot); 198 String mainContentTypeId = configuration.getValue(); 199 200 Collection<String> typesIds = new ArrayList<>(); 201 typesIds.add(mainContentTypeId); 202 203 boolean inherit = configuration.getAttributeAsBoolean("inherit", defaultInherit); 204 if (inherit) 205 { 206 typesIds.addAll(_contentTypesEP.getSubTypes(mainContentTypeId)); 207 } 208 209 String busMessageType = configuration.getAttribute("bus-message-type", defaultBusMessageType); 210 211 return new TreeConfigurationContentType(canBeRoot, typesIds, busMessageType); 212 } 213 214 @Override 215 public String getUIToolRole() 216 { 217 _lazyConfigure(); 218 return _uiToolRole; 219 } 220 221 @Override 222 public Set<TreeConfigurationElements> getElements() 223 { 224 _lazyConfigure(); 225 return _elements; 226 } 227 228}