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