001/* 002 * Copyright 2023 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.workspaces.initialization; 017 018import java.io.InputStream; 019import java.util.HashMap; 020import java.util.Map; 021import java.util.Optional; 022 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.configuration.DefaultConfigurationBuilder; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.avalon.framework.service.Serviceable; 030import org.apache.commons.lang3.StringUtils; 031import org.apache.excalibur.source.Source; 032 033import org.ametys.core.observation.ObservationManager; 034import org.ametys.core.user.CurrentUserProvider; 035import org.ametys.core.util.filereloader.FileReloader; 036import org.ametys.core.util.filereloader.FileReloaderUtils; 037import org.ametys.plugins.workspaces.PagePopulator; 038import org.ametys.runtime.plugin.component.AbstractLogEnabled; 039import org.ametys.web.repository.page.ModifiableSitemapElement; 040import org.ametys.web.repository.page.Page; 041 042/** 043 * Implementation of {@link PageInitializer} using a configuration to define the page and its content. 044 * 045 * By default, priority is set to 100 046 */ 047public class DefaultStaticPageInitializer extends AbstractLogEnabled implements PageInitializer, Configurable, Serviceable 048{ 049 /** the current user provider */ 050 protected CurrentUserProvider _currentUserProvider; 051 /** the observation manager */ 052 protected ObservationManager _observationManager; 053 054 private PagePopulator _pagePopulator; 055 private Map<String, Configuration> _pageModels = new HashMap<>(); 056 private int _priority; 057 private String _path; 058 private FileReloaderUtils _fileReloader; 059 060 public void configure(Configuration configuration) throws ConfigurationException 061 { 062 _path = configuration.getChild("model").getAttribute("path"); 063 _priority = configuration.getChild("priority", true).getValueAsInteger(100); 064 } 065 066 public void service(ServiceManager manager) throws ServiceException 067 { 068 _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 069 _observationManager = (ObservationManager) manager.lookup(ObservationManager.ROLE); 070 _pagePopulator = (PagePopulator) manager.lookup(PagePopulator.ROLE); 071 _fileReloader = (FileReloaderUtils) manager.lookup(FileReloaderUtils.ROLE); 072 } 073 074 public int getPriority() 075 { 076 return _priority; 077 } 078 079 public Optional<? extends Page> createPage(ModifiableSitemapElement parent) 080 { 081 Configuration model = _loadPageModel(parent.getSite().getSkinId()); 082 // null if the skin has no model for the given path 083 if (model != null) 084 { 085 try 086 { 087 return _pagePopulator.initPage(parent, model); 088 } 089 catch (ConfigurationException e) 090 { 091 getLogger().error("An error occurred during the page initialization because the configuration was invalid.", e); 092 } 093 catch (Exception e) 094 { 095 getLogger().error("An unexpected error occurred during the page initialization.", e); 096 } 097 } 098 return Optional.empty(); 099 } 100 101 private Configuration _loadPageModel(String skinId) 102 { 103 try 104 { 105 String skinPath = StringUtils.replace(_path, "{skinId}", skinId); 106 _fileReloader.updateFile(skinPath, new PageModelReloader(skinPath, this)); 107 108 // The reloader is in charge of storing and updating the model 109 return _pageModels.get(skinPath); 110 } 111 catch (Exception e) 112 { 113 throw new IllegalStateException("No configuration found at path '" + _path + "' for skin '" + skinId + "'.", e); 114 } 115 } 116 117 /** 118 * Store the page model located at a given path 119 * @param path the path to retrieve the model 120 * @param cfg the page model 121 */ 122 public void setModel(String path, Configuration cfg) 123 { 124 _pageModels.put(path, cfg); 125 } 126 127 /** 128 * File reloader for the page model configuration 129 * @param path the file path. 130 * @param initializer the initializer component 131 */ 132 protected static record PageModelReloader(String path, DefaultStaticPageInitializer initializer) implements FileReloader { 133 public void updateFile(String sourceUrl, Source source, InputStream is) throws Exception 134 { 135 if (is != null) 136 { 137 initializer.setModel(path, new DefaultConfigurationBuilder().build(is, source.getURI())); 138 } 139 } 140 141 public String getId(String sourceUrl) 142 { 143 return PageModelReloader.class.getName() + "#" + path; 144 } 145 } 146 147}