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.web.indexing.solr; 017 018import java.util.List; 019 020import org.apache.avalon.framework.service.ServiceException; 021import org.apache.avalon.framework.service.ServiceManager; 022import org.apache.solr.client.solrj.SolrClient; 023 024import org.ametys.cms.content.indexing.solr.SolrFieldNames; 025import org.ametys.cms.indexing.IndexingException; 026import org.ametys.cms.indexing.solr.SolrWorkspaceIndexer; 027import org.ametys.core.schedule.progression.ContainerProgressionTracker; 028import org.ametys.core.schedule.progression.SimpleProgressionTracker; 029import org.ametys.plugins.repository.AmetysObject; 030import org.ametys.plugins.repository.AmetysObjectIterable; 031import org.ametys.plugins.repository.AmetysObjectResolver; 032import org.ametys.plugins.repository.RepositoryConstants; 033import org.ametys.plugins.repository.TraversableAmetysObject; 034import org.ametys.plugins.repository.UnknownAmetysObjectException; 035import org.ametys.runtime.config.Config; 036import org.ametys.runtime.i18n.I18nizableText; 037import org.ametys.web.explorer.ResourceHelper; 038import org.ametys.web.indexing.SiteIndexer; 039import org.ametys.web.repository.site.Site; 040import org.ametys.web.repository.site.SiteManager; 041 042/** 043 * Web-specific component indexing a workspace in a Solr server. 044 */ 045public class SolrWebWorkspaceIndexer extends SolrWorkspaceIndexer 046{ 047 /** The site manager. */ 048 protected SiteManager _siteManager; 049 050 /** The site indexer. */ 051 protected SiteIndexer _siteIndexer; 052 053 /** The Ametys object resolver. */ 054 protected AmetysObjectResolver _resolver; 055 056 @Override 057 public void service(ServiceManager manager) throws ServiceException 058 { 059 super.service(manager); 060 061 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 062 _siteIndexer = (SiteIndexer) manager.lookup(SiteIndexer.ROLE); 063 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 064 } 065 066 private void _createProgressionTrackerStepsForDoIndex(ContainerProgressionTracker progressionTracker) 067 { 068 progressionTracker.addSimpleStep("unindexing", new I18nizableText("plugin.cms", "PLUGINS_CMS_SCHEDULER_GLOBAL_INDEXATION_UNINDEXING_DOCUMENTS_STEP_LABEL")); 069 070 ContainerProgressionTracker sitesProgressionTracker = progressionTracker.addContainerStep("sites", new I18nizableText("plugin.web", "PLUGINS_WEB_SCHEDULABLE_SITE_INDEXATION_SITES_STEPS_LABEL")); 071 try (AmetysObjectIterable<Site> sites = _siteManager.getSites()) 072 { 073 for (Site site : sites) 074 { 075 sitesProgressionTracker.addContainerStep(site.getName(), new I18nizableText("plugin.web", "PLUGINS_WEB_SCHEDULABLE_SITE_INDEXATION_SITE_STEPS_LABEL", List.of(site.getName()))); 076 } 077 } 078 catch (Exception e) 079 { 080 // Ignoring, it will be rethrown just after 081 } 082 083 progressionTracker.addSimpleStep("contents", new I18nizableText("plugin.web", "PLUGINS_WEB_SCHEDULABLE_SITE_INDEXATION_CONTENT_STEP_LABEL")); 084 085 progressionTracker.addContainerStep("plugins", new I18nizableText("plugin.web", "PLUGINS_WEB_SCHEDULABLE_SITE_INDEXATION_NOSITES_CONTENTS_PLUGINS_STEPS_LABEL")); 086 087 progressionTracker.addSimpleStep("resources", new I18nizableText("plugin.web", "PLUGINS_WEB_SCHEDULABLE_SITE_INDEXATION_NOSITES_RESOURCES_STEPS_LABEL")); 088 089 progressionTracker.addSimpleStep("trashElements", new I18nizableText("plugin.cms", "PLUGINS_CMS_SCHEDULER_GLOBAL_INDEXATION_TRASH_ELEMENTS_STEP_LABEL")); 090 091 _createAdditionalDocumentsProgressionTrackerSteps(progressionTracker); 092 093 progressionTracker.addSimpleStep("commitoptimize", new I18nizableText("plugin.cms", "PLUGINS_CMS_SCHEDULER_GLOBAL_INDEXATION_SAVING_COMMIT_AND_OPTIMIZE_STEP_LABEL")); 094 } 095 096 @Override 097 protected void doIndex(String workspaceName, ContainerProgressionTracker progressionTracker) throws IndexingException 098 { 099 _createProgressionTrackerStepsForDoIndex(progressionTracker); 100 101 SolrClient solrClient = _solrClientProvider.getUpdateClient(workspaceName, false); 102 103 try (AmetysObjectIterable<Site> sites = _siteManager.getSites()) 104 { 105 // First, unindex all documents. 106 _solrIndexer.unindexAllDocuments(workspaceName, solrClient); 107 ((SimpleProgressionTracker) progressionTracker.getStep("unindexing")).increment(); 108 109 // Index each site. 110 ContainerProgressionTracker sitesProgressionTracker = progressionTracker.getStep("sites"); 111 for (Site site : sites) 112 { 113 _siteIndexer.indexSite(site.getName(), workspaceName, solrClient, sitesProgressionTracker.getStep(site.getName())); 114 } 115 116 // Index contents in the out-of-site content root. 117 indexContentRoot(workspaceName, solrClient, progressionTracker.getStep("contents")); 118 indexPluginsContentRoot(workspaceName, solrClient, progressionTracker.getStep("plugins")); 119 120 // Index shared resources. 121 indexSharedResources(workspaceName, solrClient, progressionTracker.getStep("resources")); 122 123 // Index all trash elements 124 _solrIndexer.indexAllTrashElements(workspaceName, solrClient, progressionTracker.getStep("trashElements")); 125 126 // Optionally index additional documents. 127 indexAdditionalDocuments(workspaceName, solrClient, progressionTracker); 128 129 _solrIndexer.commit(workspaceName, solrClient); 130 // Optimize once when done. 131 _solrIndexer.optimize(workspaceName, solrClient); 132 ((SimpleProgressionTracker) progressionTracker.getStep("commitoptimize")).increment(); 133 } 134 catch (Exception e) 135 { 136 getLogger().error("Error indexing the workspace '" + workspaceName + "'.", e); 137 throw new IndexingException("Error indexing the workspace '" + workspaceName + "'.", e); 138 } 139 } 140 141 /** 142 * Index the out-of-site contents. 143 * @param workspaceName The workspace name 144 * @param solrClient The solr client to use 145 * @param progressionTracker The progression tracker 146 * @throws Exception If an error occurs. 147 */ 148 protected void indexContentRoot(String workspaceName, SolrClient solrClient, SimpleProgressionTracker progressionTracker) throws Exception 149 { 150 try 151 { 152 TraversableAmetysObject contentRoot = _resolver.resolveByPath("/" + RepositoryConstants.NAMESPACE_PREFIX + ":contents"); 153 _solrIndexer.indexContents(contentRoot.getChildren(), workspaceName, true, solrClient, progressionTracker); 154 } 155 catch (UnknownAmetysObjectException e) 156 { 157 // Ignore if the content root doesn't exist in a workspace. 158 progressionTracker.setSize(0); 159 } 160 } 161 162 /** 163 * Index the contents stored by plugins 164 * @param workspaceName The workspace name 165 * @param solrClient The solr client to use 166 * @param progressionTracker The progression tracker 167 * @throws Exception If an error occurs. 168 */ 169 protected void indexPluginsContentRoot(String workspaceName, SolrClient solrClient, ContainerProgressionTracker progressionTracker) throws Exception 170 { 171 try 172 { 173 TraversableAmetysObject pluginsNode = _resolver.resolveByPath("/" + RepositoryConstants.NAMESPACE_PREFIX + ":plugins"); 174 175 for (AmetysObject pluginNode : pluginsNode.getChildren()) 176 { 177 if (pluginNode instanceof TraversableAmetysObject) 178 { 179 try 180 { 181 AmetysObject rootContents = ((TraversableAmetysObject) pluginNode).getChild(RepositoryConstants.NAMESPACE_PREFIX + ":contents"); 182 if (rootContents instanceof TraversableAmetysObject) 183 { 184 progressionTracker.addSimpleStep(pluginNode.getName(), new I18nizableText("plugin.web", "PLUGINS_WEB_SCHEDULABLE_SITE_INDEXATION_NOSITES_CONTENTS_PLUGIN_STEPS_LABEL", List.of(pluginNode.getName()))); 185 } 186 } 187 catch (UnknownAmetysObjectException e) 188 { 189 // Ignore if the content root doesn't exist in a plugin's node. 190 } 191 } 192 } 193 194 if (progressionTracker.getSize() == 0) 195 { 196 SimpleProgressionTracker noPluginsTracker = progressionTracker.addSimpleStep("noplugins", new I18nizableText("")); 197 noPluginsTracker.setSize(0); 198 } 199 else 200 { 201 for (AmetysObject pluginNode : pluginsNode.getChildren()) 202 { 203 if (pluginNode instanceof TraversableAmetysObject) 204 { 205 try 206 { 207 AmetysObject rootContents = ((TraversableAmetysObject) pluginNode).getChild(RepositoryConstants.NAMESPACE_PREFIX + ":contents"); 208 if (rootContents instanceof TraversableAmetysObject) 209 { 210 _solrIndexer.indexContents(((TraversableAmetysObject) rootContents).getChildren(), workspaceName, true, solrClient, progressionTracker.getStep(pluginNode.getName())); 211 } 212 } 213 catch (UnknownAmetysObjectException e) 214 { 215 // Ignore if the content root doesn't exist in a plugin's node. 216 } 217 218 } 219 } 220 } 221 } 222 catch (UnknownAmetysObjectException e) 223 { 224 // Ignore if the plugin's node doesn't exist in a workspace. 225 progressionTracker.addSimpleStep("empty", new I18nizableText("")).setSize(0); 226 } 227 } 228 229 230 /** 231 * Index the shared resources. 232 * @param workspaceName The workspace name 233 * @param solrClient The solr client to use 234 * @param progressionTracker The progression tracker 235 * @throws Exception If an error occurs. 236 */ 237 protected void indexSharedResources(String workspaceName, SolrClient solrClient, SimpleProgressionTracker progressionTracker) throws Exception 238 { 239 boolean useShared = Config.getInstance().getValue("resources.shared.folder"); 240 if (useShared) 241 { 242 try 243 { 244 TraversableAmetysObject sharedResources = _resolver.resolveByPath(ResourceHelper.SHARED_RESOURCE_PATH + "/all"); 245 _solrIndexer.indexResources(sharedResources.getChildren(), SolrFieldNames.TYPE_RESOURCE, sharedResources, workspaceName, solrClient, progressionTracker); 246 } 247 catch (UnknownAmetysObjectException e) 248 { 249 // Ignore if the shared resource root doesn't exist in a workspace. 250 progressionTracker.setSize(0); 251 } 252 } 253 else 254 { 255 progressionTracker.setSize(0); 256 } 257 } 258 259}