001/* 002 * (C) Copyright 2007-2010 Nuxeo SA (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.scheduler; 020 021import java.io.Serializable; 022import java.util.HashMap; 023import java.util.Map; 024 025import javax.security.auth.login.LoginContext; 026import javax.security.auth.login.LoginException; 027 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.ecm.core.api.impl.UserPrincipal; 031import org.nuxeo.ecm.core.event.Event; 032import org.nuxeo.ecm.core.event.EventContext; 033import org.nuxeo.ecm.core.event.EventService; 034import org.nuxeo.ecm.core.event.impl.EventContextImpl; 035import org.nuxeo.ecm.core.event.impl.EventImpl; 036import org.nuxeo.runtime.api.Framework; 037import org.nuxeo.runtime.api.login.LoginAs; 038import org.nuxeo.runtime.transaction.TransactionHelper; 039import org.quartz.Job; 040import org.quartz.JobDataMap; 041import org.quartz.JobExecutionContext; 042import org.quartz.JobExecutionException; 043 044/** 045 * A Quartz job whose execution sends a configured event. 046 */ 047public class EventJob implements Job { 048 049 private static final Log log = LogFactory.getLog(EventJob.class); 050 051 /** 052 * Job execution to send the configured event. 053 */ 054 @Override 055 public void execute(JobExecutionContext context) throws JobExecutionException { 056 JobDataMap dataMap = context.getJobDetail().getJobDataMap(); 057 058 // switch to the Nuxeo classloader so that the event listeners 059 // work as usual 060 061 ClassLoader oldCL = Thread.currentThread().getContextClassLoader(); 062 ClassLoader nuxeoCL = getClass().getClassLoader(); 063 Thread.currentThread().setContextClassLoader(nuxeoCL); 064 try { 065 execute(dataMap); 066 } catch (LoginException e) { 067 String eventId = dataMap.getString("eventId"); 068 log.error("Error while processing scheduled event id: " + eventId, e); 069 } finally { 070 Thread.currentThread().setContextClassLoader(oldCL); 071 } 072 } 073 074 protected void execute(JobDataMap dataMap) throws LoginException { 075 String eventId = dataMap.getString("eventId"); 076 String eventCategory = dataMap.getString("eventCategory"); 077 String username = dataMap.getString("username"); 078 079 SchedulerService scheduler = Framework.getService(SchedulerService.class); 080 if (scheduler == null || !scheduler.hasApplicationStarted()) { 081 // too early 082 return; 083 } 084 085 EventService eventService = Framework.getService(EventService.class); 086 if (eventService == null) { 087 log.error("Cannot find EventService"); 088 return; 089 } 090 091 LoginContext loginContext = null; 092 try { 093 // login 094 if (username == null) { 095 loginContext = Framework.login(); 096 } else { 097 if (Framework.getService(LoginAs.class) != null) { 098 loginContext = Framework.loginAsUser(username); 099 } else if (!Framework.isTestModeSet()) { 100 log.error("LoginAs service not available"); 101 } 102 } 103 104 // set up event context 105 UserPrincipal principal = new UserPrincipal(username, null, false, false); 106 EventContext eventContext = new EventContextImpl(null, principal); 107 eventContext.setProperty("category", eventCategory); 108 eventContext.setProperties(getWrappedMap(dataMap)); 109 Event event = new EventImpl(eventId, eventContext); 110 111 // start transaction 112 boolean tx = TransactionHelper.startTransaction(); 113 114 // send event 115 log.debug("Sending scheduled event id=" + eventId + ", category=" + eventCategory + ", username=" 116 + username); 117 boolean ok = false; 118 try { 119 eventService.fireEvent(event); 120 ok = true; 121 } finally { 122 if (tx) { 123 if (!ok) { 124 TransactionHelper.setTransactionRollbackOnly(); 125 } 126 TransactionHelper.commitOrRollbackTransaction(); 127 } 128 } 129 } finally { 130 // logout 131 if (loginContext != null) { 132 loginContext.logout(); 133 } 134 } 135 } 136 137 /** 138 * @return a plain map from a JobDataMap object 139 * @since 7.10 140 */ 141 private Map<String, Serializable> getWrappedMap(JobDataMap jobMap) { 142 Map<String, Serializable> map = new HashMap<String, Serializable>(); 143 for (String key : jobMap.getKeys()) { 144 map.put(key, (Serializable) jobMap.get(key)); 145 } 146 return map; 147 } 148 149}