001/* 002 * Copyright 2016 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.live; 017 018import java.time.ZonedDateTime; 019import java.util.HashMap; 020import java.util.Map; 021import java.util.Optional; 022 023import javax.jcr.Repository; 024 025import org.apache.avalon.framework.CascadingRuntimeException; 026import org.apache.avalon.framework.component.WrapperComponentManager; 027import org.apache.avalon.framework.context.Context; 028import org.apache.avalon.framework.context.ContextException; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.cocoon.Constants; 032import org.apache.cocoon.Processor; 033import org.apache.cocoon.components.CocoonComponentManager; 034import org.apache.cocoon.environment.background.BackgroundEnvironment; 035import org.apache.cocoon.util.log.SLF4JLoggerAdapter; 036import org.quartz.JobDataMap; 037import org.quartz.JobExecutionContext; 038 039import org.ametys.cms.schedule.AbstractSendingMailSchedulable; 040import org.ametys.core.schedule.progression.ContainerProgressionTracker; 041import org.ametys.core.user.UserIdentity; 042import org.ametys.plugins.core.schedule.Scheduler; 043import org.ametys.runtime.servlet.RuntimeServlet; 044import org.ametys.runtime.servlet.RuntimeServlet.ForcedMainteanceInformations; 045import org.ametys.runtime.servlet.RuntimeServlet.MaintenanceStatus; 046import org.ametys.runtime.servlet.RuntimeServlet.RunMode; 047 048/** 049 * Abstract schedulable for rebuilding the live workspace. 050 */ 051public abstract class AbstractRebuildLiveWorkspaceSchedulable extends AbstractSendingMailSchedulable 052{ 053 /** The key for the maintenance mode to rebuild the live workspace */ 054 private static final String __JOBDATAMAP_MAINTENANCE_KEY = Scheduler.PARAM_VALUES_PREFIX + "maintenance"; 055 056 /** The key for the reindexation at the end of the live workspace rebuild */ 057 private static final String __JOBDATAMAP_REINDEX_KEY = Scheduler.PARAM_VALUES_PREFIX + "reindex"; 058 059 /** The cocoon environment context. */ 060 protected org.apache.cocoon.environment.Context _environmentContext; 061 /** Component for rebuilding the live workspace */ 062 protected RebuildLiveComponent _rebuildLiveComponent; 063 /** JCR repository */ 064 protected Repository _repository; 065 066 @Override 067 public void contextualize(Context context) throws ContextException 068 { 069 super.contextualize(context); 070 _environmentContext = (org.apache.cocoon.environment.Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); 071 } 072 073 @Override 074 public void service(ServiceManager manager) throws ServiceException 075 { 076 super.service(manager); 077 _rebuildLiveComponent = (RebuildLiveComponent) manager.lookup(RebuildLiveComponent.ROLE); 078 _repository = (Repository) manager.lookup(Repository.class.getName()); 079 } 080 081 @Override 082 protected void _doExecute(JobExecutionContext context, ContainerProgressionTracker progressionTracker) throws Exception 083 { 084 getLogger().info("Time to rebuild live workspace"); 085 086 087 // Create environment 088 Map<String, Object> env = _createAndEnterGenerationEnvironment(); 089 090 JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); 091 Boolean maintenance = (Boolean) jobDataMap.get(__JOBDATAMAP_MAINTENANCE_KEY); 092 UserIdentity userIdentity = UserIdentity.stringToUserIdentity(jobDataMap.getString(Scheduler.KEY_RUNNABLE_USERIDENTITY)); 093 094 RunMode oldMode = null; 095 try 096 { 097 // Maintenance mode 098 if (Boolean.TRUE.equals(maintenance)) 099 { 100 oldMode = RuntimeServlet.getRunMode(); 101 102 if (oldMode != RunMode.MAINTENANCE) 103 { 104 RuntimeServlet.setMaintenanceStatus(MaintenanceStatus.FORCED, new ForcedMainteanceInformations("", userIdentity, ZonedDateTime.now())); 105 RuntimeServlet.setRunMode(RunMode.MAINTENANCE); 106 } 107 } 108 109 // Reindex (true by default, keep the old value) 110 Boolean reindex = Optional.ofNullable(jobDataMap.getBooleanValue(__JOBDATAMAP_REINDEX_KEY)).orElse(Boolean.TRUE); 111 112 _rebuildLiveWorkspace(reindex, context, progressionTracker); 113 } 114 finally 115 { 116 _leaveGenerationEnvironment(env); 117 118 if (Boolean.TRUE.equals(maintenance) && oldMode != RunMode.MAINTENANCE) 119 { 120 RuntimeServlet.setRunMode(oldMode); 121 RuntimeServlet.setMaintenanceStatus(MaintenanceStatus.NONE, null); 122 } 123 } 124 } 125 126 /** 127 * Implements this method for building the live. 128 * @param reindex <code>true</code> to force reindexation at the end of the rebuild 129 * @param context the context 130 * @param progressionTracker The progression tracker 131 * @throws Exception if an error occurred 132 */ 133 protected abstract void _rebuildLiveWorkspace(boolean reindex, JobExecutionContext context, ContainerProgressionTracker progressionTracker) throws Exception; 134 135 private Map<String, Object> _createAndEnterGenerationEnvironment() 136 { 137 BackgroundEnvironment environment; 138 Processor processor; 139 140 try 141 { 142 environment = new BackgroundEnvironment(new SLF4JLoggerAdapter(getLogger()), _environmentContext); 143 processor = (Processor) _smanager.lookup(Processor.ROLE); 144 } 145 catch (Exception e) 146 { 147 throw new CascadingRuntimeException("Error during environment's setup.", e); 148 } 149 150 Object processingKey = CocoonComponentManager.startProcessing(environment); 151 int environmentDepth = CocoonComponentManager.markEnvironment(); 152 153 CocoonComponentManager.enterEnvironment(environment, new WrapperComponentManager(_smanager), processor); 154 155 Map<String, Object> result = new HashMap<>(); 156 157 result.put("environment", environment); 158 result.put("processor", processor); 159 result.put("processingKey", processingKey); 160 result.put("environmentDepth", Integer.valueOf(environmentDepth)); 161 162 return result; 163 } 164 165 private void _leaveGenerationEnvironment(Map environmentInformation) 166 { 167 BackgroundEnvironment environment = (BackgroundEnvironment) environmentInformation.get("environment"); 168 Processor processor = (Processor) environmentInformation.get("processor"); 169 Object processingKey = environmentInformation.get("processingKey"); 170 int environmentDepth = ((Integer) environmentInformation.get("environmentDepth")).intValue(); 171 172 CocoonComponentManager.leaveEnvironment(); 173 CocoonComponentManager.endProcessing(environment, processingKey); 174 175 try 176 { 177 CocoonComponentManager.checkEnvironment(environmentDepth, new SLF4JLoggerAdapter(getLogger())); 178 } 179 catch (Exception e) 180 { 181 throw new CascadingRuntimeException("Error checking the environment", e); 182 } 183 184 _smanager.release(processor); 185 } 186}