001/* 002 * Copyright 2021 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.odf.schedulable; 017 018import java.io.IOException; 019import java.util.HashMap; 020import java.util.Map; 021import java.util.Objects; 022 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.commons.lang3.StringUtils; 026import org.apache.commons.lang3.exception.ExceptionUtils; 027import org.quartz.JobDataMap; 028import org.quartz.JobExecutionContext; 029import org.quartz.JobExecutionException; 030 031import org.ametys.cms.schedule.AbstractSendingMailSchedulable; 032import org.ametys.core.schedule.progression.ContainerProgressionTracker; 033import org.ametys.core.schedule.progression.SimpleProgressionTracker; 034import org.ametys.core.ui.mail.StandardMailBodyHelper; 035import org.ametys.odf.catalog.Catalog; 036import org.ametys.odf.catalog.CatalogsManager; 037import org.ametys.plugins.core.schedule.Scheduler; 038import org.ametys.runtime.i18n.I18nizableText; 039import org.ametys.runtime.i18n.I18nizableTextParameter; 040 041/** 042 * Schedulable to copy a catalog. 043 */ 044public class CopyCatalogSchedulable extends AbstractSendingMailSchedulable 045{ 046 047 /** Schedulable ID */ 048 public static final String SCHEDULABLE_ID = CopyCatalogSchedulable.class.getName(); 049 050 /** The key for the source catalog */ 051 public static final String JOBDATAMAP_SRC_CATALOG_KEY = "srcCatalog"; 052 053 /** The key for the destinationcatalog */ 054 public static final String JOBDATAMAP_DEST_CATALOG_KEY = "destCatalog"; 055 056 /** The catalogs manager */ 057 protected CatalogsManager _catalogsManager; 058 059 @Override 060 public void service(ServiceManager manager) throws ServiceException 061 { 062 super.service(manager); 063 _catalogsManager = (CatalogsManager) manager.lookup(CatalogsManager.ROLE); 064 } 065 066 @Override 067 protected void _doExecute(JobExecutionContext context, ContainerProgressionTracker progressionTracker) throws Exception 068 { 069 SimpleProgressionTracker beforeCopyChecks = progressionTracker.addSimpleStep("before-copy-checks-step", new I18nizableText("plugin.odf", "PLUGINS_ODF_SCHEDULABLE_COPY_CATALOG_BEFORE_COPY_CHECKS_STEP_LABEL")); 070 071 beforeCopyChecks.setSize(1); 072 073 JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); 074 075 // Check source catalog 076 String srcCatalogName = jobDataMap.getString(Scheduler.PARAM_VALUES_PREFIX + JOBDATAMAP_SRC_CATALOG_KEY); 077 if (StringUtils.isEmpty(srcCatalogName)) 078 { 079 throw new JobExecutionException("The source catalog name cannot be empty."); 080 } 081 082 // Check destination catalog 083 String destCatalogName = jobDataMap.getString(Scheduler.PARAM_VALUES_PREFIX + JOBDATAMAP_DEST_CATALOG_KEY); 084 if (StringUtils.isEmpty(destCatalogName)) 085 { 086 throw new JobExecutionException("The destination catalog name cannot be empty."); 087 } 088 089 // Check that source and destination catalog are different 090 if (Objects.equals(srcCatalogName, destCatalogName)) 091 { 092 throw new JobExecutionException("The source and destination catalogs cannot be the same."); 093 } 094 095 // Check the existence of the source catalog 096 Catalog srcCatalog = _catalogsManager.getCatalog(srcCatalogName); 097 if (srcCatalog == null) 098 { 099 throw new JobExecutionException("The source catalog should exist."); 100 } 101 102 // Check the existence of the destination catalog 103 Catalog destCatalog = _catalogsManager.getCatalog(destCatalogName); 104 if (destCatalog == null) 105 { 106 destCatalog = _catalogsManager.createCatalog(destCatalogName, destCatalogName); 107 } 108 109 beforeCopyChecks.increment(); 110 111 _catalogsManager.copyCatalog(destCatalog, srcCatalog, progressionTracker); 112 } 113 114 @Override 115 protected I18nizableText _getSuccessMailSubject(JobExecutionContext context) throws Exception 116 { 117 return new I18nizableText("plugin.odf", "PLUGINS_ODF_SCHEDULABLE_COPY_CATALOG_SUCCESS_MAIL_SUBJECT"); 118 } 119 120 @Override 121 protected boolean _isMailBodyInHTML(JobExecutionContext context) throws Exception 122 { 123 return true; 124 } 125 126 @Override 127 protected String _getSuccessMailBody(JobExecutionContext context, String language) throws Exception 128 { 129 try 130 { 131 return StandardMailBodyHelper.newHTMLBody() 132 .withTitle(_getSuccessMailSubject(context)) 133 .withMessage(new I18nizableText("plugin.odf", "PLUGINS_ODF_SCHEDULABLE_COPY_CATALOG_SUCCESS_MAIL_BODY", _getCommonI18nParams(context))) 134 .withLanguage(language) 135 .build(); 136 } 137 catch (IOException e) 138 { 139 getLogger().warn("Failed to build HTML email body for catalog copy result. Fallback to no wrapped email", e); 140 return _i18nUtils.translate(new I18nizableText("plugin.odf", "PLUGINS_ODF_SCHEDULABLE_COPY_CATALOG_SUCCESS_MAIL_BODY", _getCommonI18nParams(context)), language); 141 } 142 } 143 144 @Override 145 protected I18nizableText _getErrorMailSubject(JobExecutionContext context) throws Exception 146 { 147 return new I18nizableText("plugin.odf", "PLUGINS_ODF_SCHEDULABLE_COPY_CATALOG_ERROR_MAIL_SUBJECT"); 148 } 149 150 @Override 151 protected String _getErrorMailBody(JobExecutionContext context, String language, Throwable throwable) throws Exception 152 { 153 try 154 { 155 String error = ExceptionUtils.getStackTrace(throwable); 156 157 return StandardMailBodyHelper.newHTMLBody() 158 .withTitle(_getErrorMailSubject(context)) 159 .withMessage(new I18nizableText("plugin.odf", "PLUGINS_ODF_SCHEDULABLE_COPY_CATALOG_ERROR_MAIL_BODY", _getCommonI18nParams(context))) 160 .withDetails(null, error, true) 161 .withLanguage(language) 162 .build(); 163 } 164 catch (IOException e) 165 { 166 getLogger().warn("Failed to build HTML email body for catalog copy result. Fallback to no wrapped email", e); 167 return _i18nUtils.translate(new I18nizableText("plugin.odf", "PLUGINS_ODF_SCHEDULABLE_COPY_CATALOG_ERROR_MAIL_BODY", _getCommonI18nParams(context)), language); 168 } 169 } 170 171 private Map<String, I18nizableTextParameter> _getCommonI18nParams(JobExecutionContext context) 172 { 173 JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); 174 175 Map<String, I18nizableTextParameter> i18nParams = new HashMap<>(); 176 i18nParams.put("srcCatalog", new I18nizableText(jobDataMap.getString(Scheduler.PARAM_VALUES_PREFIX + JOBDATAMAP_SRC_CATALOG_KEY))); 177 i18nParams.put("destCatalog", new I18nizableText(jobDataMap.getString(Scheduler.PARAM_VALUES_PREFIX + JOBDATAMAP_DEST_CATALOG_KEY))); 178 return i18nParams; 179 } 180}