001/* 002 * Copyright 2013 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.ui.model; 017 018import java.io.File; 019import java.io.FileInputStream; 020import java.io.InputStream; 021import java.util.HashSet; 022import java.util.Set; 023 024import org.apache.avalon.framework.configuration.Configuration; 025import org.apache.avalon.framework.configuration.ConfigurationException; 026import org.apache.avalon.framework.configuration.DefaultConfiguration; 027import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.cocoon.Constants; 031import org.apache.cocoon.environment.Context; 032 033import org.ametys.cms.contenttype.ContentType; 034import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 035import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint; 036 037/** 038 * Extension point for {@link SearchUIModel}s. 039 */ 040public class SearchUIModelExtensionPoint extends AbstractThreadSafeComponentExtensionPoint<SearchUIModel> 041{ 042 /** The component role */ 043 public static final String ROLE = SearchUIModelExtensionPoint.class.getName(); 044 045 private ContentTypeExtensionPoint _cTypeEP; 046 047 private Set<String> _filesLoaded; 048 049 /** 050 * Create the instance 051 */ 052 public SearchUIModelExtensionPoint() 053 { 054 super(); 055 _filesLoaded = new HashSet<>(); 056 } 057 058 @Override 059 public void service(ServiceManager manager) throws ServiceException 060 { 061 super.service(manager); 062 _cTypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 063 } 064 065 @Override 066 public void addExtension(String id, String pluginName, String featureName, Configuration configuration) throws ConfigurationException 067 { 068 if (_filesLoaded.contains(id)) 069 { 070 getLogger().warn("The search model extension '" + id + "' from feature '" + pluginName + "/" + featureName + "' will be ignored. It has already been loaded from the file in WEB-INF/param/search/" + id.substring("search-ui.".length()) + ".xml"); 071 } 072 else 073 { 074 super.addExtension(id, pluginName, featureName, configuration); 075 } 076 } 077 078 @Override 079 public void initialize() throws Exception 080 { 081 super.initialize(); 082 083 try 084 { 085 Context ctx = (Context) _context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); 086 087 File root = new File(ctx.getRealPath("/WEB-INF/param/search")); 088 089 if (root.exists()) 090 { 091 File[] files = root.listFiles(file -> !file.isDirectory() && file.getName().endsWith(".xml")); 092 093 for (File modelFile : files) 094 { 095 String fileName = modelFile.getName(); 096 String id = "search-ui." + fileName.substring(0, fileName.lastIndexOf('.')); 097 _filesLoaded.add(id); 098 099 if (super.hasExtension(id)) 100 { 101 throw new IllegalArgumentException("The search tool model of id " + id + " at " + modelFile.getAbsolutePath() + " is already declared."); 102 } 103 104 try (InputStream is = new FileInputStream(modelFile)) 105 { 106 107 DefaultConfiguration conf = new DefaultConfiguration("extension"); 108 109 Configuration c = new DefaultConfigurationBuilder(true).build(is); 110 111 conf.setAttribute("id", id); 112 conf.addChild(c); 113 114 addComponent("unknown", "unknown", id, StaticSearchUIModel.class, conf); 115 } 116 catch (Exception e) 117 { 118 getLogger().error("Error initializing search model '" + id + "' from file '" + modelFile.getAbsolutePath() + "'.", e); 119 } 120 } 121 } 122 123 // TODO Provide a component to generate SearchModel corresponding to contents on the fly? 124 Set<String> cTypeIds = _cTypeEP.getExtensionsIds(); 125 for (String cTypeId : cTypeIds) 126 { 127 ContentType cType = _cTypeEP.getExtension(cTypeId); 128 if (cType != null && cType.isSimple() && !cType.isAbstract()) 129 { 130 String id = "simple-search-ui." + cTypeId; 131 DefaultConfiguration conf = new DefaultConfiguration("extension"); 132 conf.setAttribute("id", id); 133 134 DefaultConfiguration cTypeConf = new DefaultConfiguration("contentType"); 135 cTypeConf.setValue(cTypeId); 136 conf.addChild(cTypeConf); 137 138 addComponent("unknown", "unknown", id, SimpleContentSearchUIModel.class, conf); 139 } 140 } 141 } 142 catch (Exception e) 143 { 144 getLogger().error("Unable to initialize search tool models", e); 145 } 146 } 147}