001/* 002 * Copyright 2025 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.indexing.solr; 017 018import java.util.Map; 019import java.util.concurrent.Callable; 020 021import org.apache.avalon.framework.service.ServiceManager; 022import org.apache.cocoon.environment.Context; 023import org.apache.cocoon.environment.ObjectModelHelper; 024import org.apache.cocoon.environment.Request; 025import org.apache.cocoon.util.log.SLF4JLoggerAdapter; 026import org.apache.solr.client.solrj.SolrClient; 027import org.slf4j.Logger; 028 029import org.ametys.cms.indexing.IndexingException; 030import org.ametys.core.engine.BackgroundEngineHelper; 031import org.ametys.core.engine.BackgroundEnvironment; 032import org.ametys.plugins.repository.AmetysObject; 033import org.ametys.plugins.repository.AmetysObjectResolver; 034import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 035 036/** 037 * Abstract implementation of {@link Callable} for {@link AmetysObject} 038 * @param <T> {@link AmetysObject} type indexing by the callable 039 */ 040public abstract class AbstractIndexerCallable<T extends AmetysObject> implements Callable<Void> 041{ 042 /** The ametys object identifier */ 043 protected String _ametysObjectId; 044 /** The workspace name */ 045 protected String _workspaceName; 046 /** The Solr client */ 047 protected SolrClient _solrClient; 048 /** The logger */ 049 protected Logger _logger; 050 051 /* Components */ 052 private ServiceManager _manager; 053 private Context _cocoonContext; 054 private AmetysObjectResolver _resolver; 055 056 /** 057 * Constructor. 058 * @param ametysObject The Ametys object, we only keep the identifier 059 * @param workspaceName The workspace name 060 * @param solrClient The Solr client 061 * @param manager The service manager 062 * @param cocoonContext The Cocoon context 063 * @param resolver The Ametys object resolver 064 * @param logger The logger 065 */ 066 public AbstractIndexerCallable(T ametysObject, String workspaceName, SolrClient solrClient, ServiceManager manager, Context cocoonContext, AmetysObjectResolver resolver, Logger logger) 067 { 068 this._ametysObjectId = ametysObject.getId(); 069 this._workspaceName = workspaceName; 070 this._solrClient = solrClient; 071 this._manager = manager; 072 this._cocoonContext = cocoonContext; 073 this._resolver = resolver; 074 this._logger = logger; 075 } 076 077 public Void call() throws Exception 078 { 079 Map<String, Object> environmentInformation = BackgroundEngineHelper.createAndEnterEngineEnvironment(_manager, _cocoonContext, new SLF4JLoggerAdapter(_logger)); 080 BackgroundEnvironment bgEnv = (BackgroundEnvironment) environmentInformation.get("environment"); 081 Request request = ObjectModelHelper.getRequest(bgEnv.getObjectModel()); 082 String currentWsp = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 083 084 try 085 { 086 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, _workspaceName); 087 088 T ametysObject = _resolver.resolveById(_ametysObjectId); 089 if (_logger.isInfoEnabled()) 090 { 091 String message = String.format("Indexing %s: %s in workspace '%s'", getObjectLabel(), ametysObject, _workspaceName); 092 _logger.info(message); 093 } 094 process(ametysObject); 095 } 096 catch (Exception e) 097 { 098 String message = String.format("Error indexing %s '%s' in the solr server on workspace '%s'", getObjectLabel(), _ametysObjectId, _workspaceName); 099 throw new IndexingException(message, e); 100 } 101 finally 102 { 103 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWsp); 104 BackgroundEngineHelper.leaveEngineEnvironment(environmentInformation); 105 } 106 107 return null; 108 } 109 110 /** 111 * Process the {@link AmetysObject} in the callable. 112 * @param ametysObject The Ametys object 113 * @throws Exception if an error occurs 114 */ 115 protected abstract void process(T ametysObject) throws Exception; 116 117 /** 118 * Get the object label for logs. 119 * @return the object label 120 */ 121 protected abstract String getObjectLabel(); 122}