001/* 002 * Copyright 2020 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.observation; 017 018import java.util.List; 019import java.util.Map; 020 021import org.apache.avalon.framework.context.Context; 022import org.apache.avalon.framework.context.ContextException; 023import org.apache.avalon.framework.context.Contextualizable; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.avalon.framework.service.Serviceable; 027import org.apache.cocoon.components.ContextHelper; 028import org.apache.cocoon.environment.Request; 029import org.apache.commons.lang.StringUtils; 030 031import org.ametys.cms.content.indexing.solr.observation.ObserverHelper; 032import org.ametys.cms.repository.Content; 033import org.ametys.core.observation.Event; 034import org.ametys.core.observation.Observer; 035import org.ametys.plugins.repository.AmetysObjectResolver; 036import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 037import org.ametys.runtime.plugin.component.AbstractLogEnabled; 038import org.ametys.web.ObservationConstants; 039import org.ametys.web.WebConstants; 040import org.ametys.web.repository.content.WebContent; 041import org.ametys.web.repository.page.Page; 042 043/** 044 * Observes when a page changed, moved or deleted and test if it's in the live 045 */ 046public class ContentOrphanStatusPart1Observer extends AbstractLogEnabled implements Observer, Serviceable, Contextualizable 047{ 048 /** Transient variables to get the id of pages that was in live before live synchronization process */ 049 public static final String PAGES_IN_LIVE_BEFORE_SYNCHRONIZATION = ContentOrphanStatusPart1Observer.class.getName() + "$pagesInLive"; 050 051 /** The Ametys object resolver */ 052 protected AmetysObjectResolver _resolver; 053 /** The avalon context */ 054 protected Context _context; 055 056 @Override 057 public void service(ServiceManager manager) throws ServiceException 058 { 059 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 060 } 061 062 @Override 063 public void contextualize(Context context) throws ContextException 064 { 065 _context = context; 066 } 067 068 @Override 069 public boolean supports(Event event) 070 { 071 return event.getId().equals(ObservationConstants.EVENT_PAGE_CHANGED) 072 || event.getId().equals(ObservationConstants.EVENT_PAGE_MOVED) 073 || event.getId().equals(ObservationConstants.EVENT_PAGE_DELETED) 074 || event.getId().equals(org.ametys.cms.ObservationConstants.EVENT_CONTENT_UNTAG_LIVE) 075 || event.getId().equals(org.ametys.cms.ObservationConstants.EVENT_CONTENT_VALIDATED); 076 } 077 078 @Override 079 public int getPriority(Event event) 080 { 081 // Will be processed BEFORE live synchronization observers, since pages have to be present in live to be unindexed. 082 return Observer.MAX_PRIORITY + 500; 083 } 084 085 @Override 086 public void observe(Event event, Map<String, Object> transientVars) throws Exception 087 { 088 if (ObserverHelper.isNotSuspendedObservationForIndexation()) 089 { 090 List<String> livePageIds = _getPageIds(event) 091 .stream() 092 .filter(this::_isInLive) 093 .toList(); 094 095 transientVars.put(PAGES_IN_LIVE_BEFORE_SYNCHRONIZATION, livePageIds); 096 } 097 } 098 099 private List<String> _getPageIds(Event event) 100 { 101 String pageId = (String) event.getArguments().get(ObservationConstants.ARGS_PAGE_ID); 102 if (StringUtils.isNotEmpty(pageId)) 103 { 104 return List.of(pageId); 105 } 106 107 Page page = (Page) event.getArguments().get(ObservationConstants.ARGS_PAGE); 108 if (page != null) 109 { 110 return List.of(page.getId()); 111 } 112 113 Content content = (Content) event.getArguments().get(org.ametys.cms.ObservationConstants.ARGS_CONTENT); 114 if (content != null && content instanceof WebContent webContent) 115 { 116 return webContent.getReferencingPages() 117 .stream() 118 .map(Page::getId) 119 .toList(); 120 } 121 122 return List.of(); 123 } 124 125 private boolean _isInLive(String pageId) 126 { 127 Request request = ContextHelper.getRequest(_context); 128 String currentWsp = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 129 try 130 { 131 // Force the workspace. 132 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, WebConstants.LIVE_WORKSPACE); 133 return _resolver.hasAmetysObjectForId(pageId); 134 } 135 finally 136 { 137 // Restore workspace 138 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWsp); 139 } 140 } 141}