001/*
002 *  Copyright 2010 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.content.consistency;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Map;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.cocoon.components.ContextHelper;
025import org.apache.cocoon.environment.Request;
026import org.quartz.JobDataMap;
027import org.quartz.JobExecutionContext;
028
029import org.ametys.cms.content.consistency.ContentConsistencyManager.ConsistenciesReport;
030import org.ametys.core.util.JSONUtils;
031import org.ametys.plugins.core.schedule.Scheduler;
032import org.ametys.plugins.repository.AmetysObjectIterable;
033import org.ametys.runtime.i18n.I18nizableText;
034import org.ametys.web.repository.site.Site;
035import org.ametys.web.repository.site.SiteManager;
036
037/**
038 * Content consistency engine: generate consistency information for all contents.
039 * Sends a report e-mail if there are inconsistencies.
040 */
041public class CheckContentConsistencySchedulable extends org.ametys.cms.content.consistency.CheckContentConsistencySchedulable
042{
043    /** The key for the name of the site containing the contents to check */
044    public static final String SITE_NAME_KEY = "siteName";
045    
046    private static final String __JOBDATAMAP_SITE_NAME_KEY = Scheduler.PARAM_VALUES_PREFIX + SITE_NAME_KEY;
047    
048    /** The utils for JSON */
049    protected JSONUtils _jsonUtils;
050    /** The site manager. */
051    protected SiteManager _siteManager;
052    /** Web version of the content consistency manager */
053    private ContentConsistencyManager _webContentConsistencyManager;
054    
055    @Override
056    public void service(ServiceManager manager) throws ServiceException
057    {
058        super.service(manager);
059        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
060        _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE);
061        _webContentConsistencyManager = (ContentConsistencyManager) manager.lookup(org.ametys.cms.content.consistency.ContentConsistencyManager.ROLE);
062    }
063    
064    @Override
065    public void execute(JobExecutionContext context) throws Exception
066    {
067        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
068        String siteAsMap = (String) jobDataMap.get(__JOBDATAMAP_SITE_NAME_KEY);
069        List<String> siteNames = _getSiteName(siteAsMap);
070        
071        try (AmetysObjectIterable<Site> sites = _siteManager.getSites())
072        {
073            // Start by checking if there is any content without site with error.
074            // If there is, we will notify every site about them.
075            ConsistenciesReport noSiteReport = _webContentConsistencyManager.checkContentsWithoutSite();
076            List<String> noSiteErrorResults = noSiteReport.results();
077            boolean contentWithoutSiteError = !noSiteReport.unchecked().isEmpty() || !noSiteErrorResults.isEmpty();
078            
079            // Iterate over sites to checks requested sites, or all of them if no requested site
080            for (Site currentSite : sites)
081            {
082                String currentSiteName = currentSite.getName();
083                
084                if (siteNames.isEmpty() || siteNames.contains(currentSiteName))
085                {
086                    // Make the site "current"
087                    Request request = ContextHelper.getRequest(_context);
088                    request.setAttribute("siteName", currentSiteName);
089                    
090                    ConsistenciesReport report = _webContentConsistencyManager.checkContentsFromSite(currentSiteName);
091                    List<String> currentSiteErrorResults = report.results();
092                    // Notify if an error was found outside of side or in site
093                    if (contentWithoutSiteError || !report.unchecked().isEmpty() || !currentSiteErrorResults.isEmpty())
094                    {
095                        
096                        List<String> mergedResults = new ArrayList<>(noSiteErrorResults);
097                        mergedResults.addAll(currentSiteErrorResults);
098                        List<String> mergedUnchecked = new ArrayList<>(noSiteReport.unchecked());
099                        mergedUnchecked.addAll(report.unchecked());
100                        _sendEmail(mergedResults, mergedUnchecked);
101                    }
102                }
103            }
104        }
105    }
106    
107    @Override
108    protected I18nizableText _getMailSubject(Map<String, String> parameters)
109    {
110        List<String> subjectParams = new ArrayList<>();
111        subjectParams.add(parameters.get("siteTitle"));
112        
113        return new I18nizableText("plugin.web", "PLUGINS_WEB_GLOBAL_CONTENT_CONSISTENCY_MAIL_SUBJECT", subjectParams);
114    }
115    
116    @Override
117    protected Map<String, String> _getEmailParams(List<String> errorResults, List<String> unchecked)
118    {
119        Map<String, String> params = super._getEmailParams(errorResults, unchecked);
120        
121        String siteName = _getCurrentSiteName();
122        
123        StringBuilder url = new StringBuilder(_baseUrl);
124        if (!_baseUrl.endsWith("/"))
125        {
126            url.append('/');
127        }
128        url.append(siteName).append("/index.html?uitool=uitool-global-consistency");
129        
130        params.put("url", url.toString());
131        
132        Site site = _siteManager.getSite(siteName);
133        String siteTitle = site.getTitle();
134        
135        params.put("siteTitle", siteTitle);
136        params.put("siteName", siteName);
137        
138        return params;
139    }
140    
141    /**
142     * Retrieves the names of the sites from given parameters
143     * @param siteAsMap JSON {@link Map} containing the sites names
144     * @return the names of the sites
145     */
146    @SuppressWarnings("unchecked")
147    protected List<String> _getSiteName(String siteAsMap)
148    {
149        Map<String, Object> mapSite = _jsonUtils.convertJsonToMap(siteAsMap);
150        return mapSite.containsKey("sites") ? (List<String>) mapSite.get("sites") : List.of();
151    }
152    
153    /**
154     * Retrieves the current site name
155     * @return the current site name
156     */
157    protected String _getCurrentSiteName()
158    {
159        Request request = ContextHelper.getRequest(_context);
160        return (String) request.getAttribute("siteName");
161    }
162}