/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.scheduler.quartz.internal;
import com.liferay.portal.kernel.dao.db.DB;
import com.liferay.portal.kernel.dao.db.DBManagerUtil;
import com.liferay.portal.kernel.dao.db.DBType;
import com.liferay.portal.kernel.json.JSONFactory;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.messaging.Message;
import com.liferay.portal.kernel.messaging.MessageBus;
import com.liferay.portal.kernel.model.Release;
import com.liferay.portal.kernel.scheduler.JobState;
import com.liferay.portal.kernel.scheduler.SchedulerEngine;
import com.liferay.portal.kernel.scheduler.SchedulerEngineHelper;
import com.liferay.portal.kernel.scheduler.SchedulerException;
import com.liferay.portal.kernel.scheduler.StorageType;
import com.liferay.portal.kernel.scheduler.TriggerState;
import com.liferay.portal.kernel.scheduler.messaging.SchedulerResponse;
import com.liferay.portal.kernel.service.PortletLocalService;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.PortalRunMode;
import com.liferay.portal.kernel.util.Props;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.ServerDetector;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.scheduler.JobStateSerializeUtil;
import com.liferay.portal.scheduler.quartz.QuartzTrigger;
import com.liferay.portal.scheduler.quartz.internal.job.MessageSenderJob;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.ObjectAlreadyExistsException;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.jdbcjobstore.UpdateLockRowSemaphore;
import org.quartz.impl.matchers.GroupMatcher;
/**
* @author Michael C. Han
* @author Bruno Farache
* @author Shuyang Zhou
* @author Wesley Gong
* @author Tina Tian
* @author Edward C. Han
*/
@Component(
enabled = false, immediate = true,
service = {QuartzSchedulerEngine.class, SchedulerEngine.class}
)
public class QuartzSchedulerEngine implements SchedulerEngine {
@Override
public void delete(String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
Set<JobKey> jobKeys = scheduler.getJobKeys(
GroupMatcher.jobGroupEquals(groupName));
for (JobKey jobKey : jobKeys) {
scheduler.deleteJob(jobKey);
}
}
catch (Exception e) {
throw new SchedulerException(
"Unable to delete jobs in group " + groupName, e);
}
}
@Override
public void delete(
String jobName, String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
jobName = fixMaxLength(jobName, _jobNameMaxLength, storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
JobKey jobKey = new JobKey(jobName, groupName);
scheduler.deleteJob(jobKey);
}
catch (Exception e) {
throw new SchedulerException(
"Unable to delete job {jobName=" + jobName + ", groupName=" +
groupName + "}",
e);
}
}
public int getDescriptionMaxLength() {
return _descriptionMaxLength;
}
public int getGroupNameMaxLength() {
return _groupNameMaxLength;
}
public int getJobNameMaxLength() {
return _jobNameMaxLength;
}
@Override
public SchedulerResponse getScheduledJob(
String jobName, String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
jobName = fixMaxLength(jobName, _jobNameMaxLength, storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
JobKey jobKey = new JobKey(jobName, groupName);
return getScheduledJob(scheduler, jobKey);
}
catch (Exception e) {
throw new SchedulerException(
"Unable to get job {jobName=" + jobName + ", groupName=" +
groupName + "}",
e);
}
}
@Override
public List<SchedulerResponse> getScheduledJobs()
throws SchedulerException {
try {
List<String> groupNames = _persistedScheduler.getJobGroupNames();
List<SchedulerResponse> schedulerResponses = new ArrayList<>();
for (String groupName : groupNames) {
schedulerResponses.addAll(
getScheduledJobs(_persistedScheduler, groupName, null));
}
groupNames = _memoryScheduler.getJobGroupNames();
for (String groupName : groupNames) {
schedulerResponses.addAll(
getScheduledJobs(_memoryScheduler, groupName, null));
}
return schedulerResponses;
}
catch (Exception e) {
throw new SchedulerException("Unable to get jobs", e);
}
}
@Override
public List<SchedulerResponse> getScheduledJobs(StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
List<String> groupNames = scheduler.getJobGroupNames();
List<SchedulerResponse> schedulerResponses = new ArrayList<>();
for (String groupName : groupNames) {
schedulerResponses.addAll(
getScheduledJobs(scheduler, groupName, storageType));
}
return schedulerResponses;
}
catch (Exception e) {
throw new SchedulerException(
"Unable to get jobs with type " + storageType, e);
}
}
@Override
public List<SchedulerResponse> getScheduledJobs(
String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
return getScheduledJobs(scheduler, groupName, storageType);
}
catch (Exception e) {
throw new SchedulerException(
"Unable to get jobs in group " + groupName, e);
}
}
@Override
public void pause(String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
Set<JobKey> jobKeys = scheduler.getJobKeys(
GroupMatcher.jobGroupEquals(groupName));
scheduler.pauseJobs(GroupMatcher.jobGroupEquals(groupName));
for (JobKey jobKey : jobKeys) {
updateJobState(scheduler, jobKey, TriggerState.PAUSED, false);
}
}
catch (Exception e) {
throw new SchedulerException(
"Unable to pause jobs in group " + groupName, e);
}
}
@Override
public void pause(String jobName, String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
jobName = fixMaxLength(jobName, _jobNameMaxLength, storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
JobKey jobKey = new JobKey(jobName, groupName);
scheduler.pauseJob(jobKey);
updateJobState(scheduler, jobKey, TriggerState.PAUSED, false);
}
catch (Exception e) {
throw new SchedulerException(
"Unable to pause job {jobName=" + jobName + ", groupName=" +
groupName + "}",
e);
}
}
@Override
public void resume(String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
Set<JobKey> jobKeys = scheduler.getJobKeys(
GroupMatcher.jobGroupEquals(groupName));
scheduler.resumeJobs(GroupMatcher.jobGroupEquals(groupName));
for (JobKey jobKey : jobKeys) {
updateJobState(scheduler, jobKey, TriggerState.NORMAL, false);
}
}
catch (Exception e) {
throw new SchedulerException(
"Unable to resume jobs in group " + groupName, e);
}
}
@Override
public void resume(
String jobName, String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
jobName = fixMaxLength(jobName, _jobNameMaxLength, storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
JobKey jobKey = new JobKey(jobName, groupName);
scheduler.resumeJob(jobKey);
updateJobState(scheduler, jobKey, TriggerState.NORMAL, false);
}
catch (Exception e) {
throw new SchedulerException(
"Unable to resume job {jobName=" + jobName + ", groupName=" +
groupName + "}",
e);
}
}
@Override
public void schedule(
com.liferay.portal.kernel.scheduler.Trigger trigger,
String description, String destination, Message message,
StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
Trigger quartzTrigger = (Trigger)trigger.getWrappedTrigger();
if (quartzTrigger == null) {
return;
}
description = fixMaxLength(
description, _descriptionMaxLength, storageType);
message = message.clone();
message.put(SchedulerEngine.GROUP_NAME, trigger.getGroupName());
message.put(SchedulerEngine.JOB_NAME, trigger.getJobName());
schedule(
scheduler, storageType, quartzTrigger, description, destination,
message);
}
catch (RuntimeException re) {
if (PortalRunMode.isTestMode()) {
StackTraceElement[] stackTraceElements = re.getStackTrace();
for (StackTraceElement stackTraceElement : stackTraceElements) {
String className = stackTraceElement.getClassName();
if (className.contains(ServerDetector.class.getName())) {
if (_log.isInfoEnabled()) {
_log.info(re, re);
}
return;
}
throw new SchedulerException("Unable to schedule job", re);
}
}
else {
throw new SchedulerException("Unable to schedule job", re);
}
}
catch (Exception e) {
throw new SchedulerException("Unable to schedule job", e);
}
}
@Override
public void shutdown() throws SchedulerException {
try {
if (!_persistedScheduler.isInStandbyMode()) {
_persistedScheduler.standby();
}
if (!_memoryScheduler.isInStandbyMode()) {
_memoryScheduler.standby();
}
}
catch (Exception e) {
throw new SchedulerException("Unable to shutdown scheduler", e);
}
}
@Override
public void start() throws SchedulerException {
try {
_persistedScheduler.start();
initJobState();
_memoryScheduler.start();
}
catch (Exception e) {
throw new SchedulerException("Unable to start scheduler", e);
}
}
@Override
public void suppressError(
String jobName, String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
jobName = fixMaxLength(jobName, _jobNameMaxLength, storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
JobKey jobKey = new JobKey(jobName, groupName);
updateJobState(scheduler, jobKey, null, true);
}
catch (Exception e) {
throw new SchedulerException(
"Unable to suppress error for job {jobName=" + jobName +
", groupName=" + groupName + "}",
e);
}
}
@Override
public void unschedule(String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
Set<JobKey> jobKeys = scheduler.getJobKeys(
GroupMatcher.jobGroupEquals(groupName));
for (JobKey jobKey : jobKeys) {
unschedule(scheduler, jobKey);
}
}
catch (Exception e) {
throw new SchedulerException(
"Unable to unschedule jobs in group " + groupName, e);
}
}
@Override
public void unschedule(
String jobName, String groupName, StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
jobName = fixMaxLength(jobName, _jobNameMaxLength, storageType);
groupName = fixMaxLength(
groupName, _groupNameMaxLength, storageType);
JobKey jobKey = new JobKey(jobName, groupName);
unschedule(scheduler, jobKey);
}
catch (Exception e) {
throw new SchedulerException(
"Unable to unschedule job {jobName=" + jobName +
", groupName=" + groupName + "}",
e);
}
}
@Override
public void update(
com.liferay.portal.kernel.scheduler.Trigger trigger,
StorageType storageType)
throws SchedulerException {
try {
Scheduler scheduler = getScheduler(storageType);
update(scheduler, trigger, storageType);
}
catch (Exception e) {
throw new SchedulerException("Unable to update trigger", e);
}
}
@Activate
protected void activate() {
_schedulerEngineEnabled = GetterUtil.getBoolean(
_props.get(PropsKeys.SCHEDULER_ENABLED));
if (!_schedulerEngineEnabled) {
return;
}
try {
_persistedScheduler = initializeScheduler(
"persisted.scheduler.", true);
_memoryScheduler = initializeScheduler("memory.scheduler.", false);
}
catch (Exception e) {
_log.error("Unable to initialize engine", e);
}
}
@Deactivate
protected void deactivate() {
if (!_schedulerEngineEnabled) {
return;
}
try {
if (!_persistedScheduler.isShutdown()) {
_persistedScheduler.shutdown(false);
}
if (!_memoryScheduler.isShutdown()) {
_memoryScheduler.shutdown(false);
}
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn("Unable to deactivate scheduler", e);
}
}
}
protected String fixMaxLength(
String argument, int maxLength, StorageType storageType) {
if ((argument == null) || (storageType != StorageType.PERSISTED)) {
return argument;
}
if (argument.length() > maxLength) {
argument = argument.substring(0, maxLength);
}
return argument;
}
protected JobState getJobState(JobDataMap jobDataMap) {
Map<String, Object> jobStateMap = (Map<String, Object>)jobDataMap.get(
SchedulerEngine.JOB_STATE);
return JobStateSerializeUtil.deserialize(jobStateMap);
}
protected Message getMessage(JobDataMap jobDataMap) {
String messageJSON = (String)jobDataMap.get(SchedulerEngine.MESSAGE);
if (_jsonFactory == null) {
throw new IllegalStateException("JSON factory not initialized");
}
return (Message)_jsonFactory.deserialize(messageJSON);
}
protected SchedulerResponse getScheduledJob(
Scheduler scheduler, JobKey jobKey)
throws Exception {
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail == null) {
return null;
}
SchedulerResponse schedulerResponse = new SchedulerResponse();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
String description = jobDataMap.getString(SchedulerEngine.DESCRIPTION);
schedulerResponse.setDescription(description);
String destinationName = jobDataMap.getString(
SchedulerEngine.DESTINATION_NAME);
schedulerResponse.setDestinationName(destinationName);
Message message = getMessage(jobDataMap);
JobState jobState = getJobState(jobDataMap);
message.put(SchedulerEngine.JOB_STATE, jobState);
schedulerResponse.setMessage(message);
StorageType storageType = StorageType.valueOf(
jobDataMap.getString(SchedulerEngine.STORAGE_TYPE));
schedulerResponse.setStorageType(storageType);
String jobName = jobKey.getName();
String groupName = jobKey.getGroup();
TriggerKey triggerKey = new TriggerKey(jobName, groupName);
Trigger trigger = scheduler.getTrigger(triggerKey);
if (trigger == null) {
schedulerResponse.setGroupName(groupName);
schedulerResponse.setJobName(jobName);
return schedulerResponse;
}
message.put(SchedulerEngine.END_TIME, trigger.getEndTime());
message.put(
SchedulerEngine.FINAL_FIRE_TIME, trigger.getFinalFireTime());
message.put(SchedulerEngine.NEXT_FIRE_TIME, trigger.getNextFireTime());
message.put(
SchedulerEngine.PREVIOUS_FIRE_TIME, trigger.getPreviousFireTime());
message.put(SchedulerEngine.START_TIME, trigger.getStartTime());
schedulerResponse.setTrigger(new QuartzTrigger(trigger));
return schedulerResponse;
}
protected List<SchedulerResponse> getScheduledJobs(
Scheduler scheduler, String groupName, StorageType storageType)
throws Exception {
groupName = fixMaxLength(groupName, _groupNameMaxLength, storageType);
List<SchedulerResponse> schedulerResponses = new ArrayList<>();
Set<JobKey> jobKeys = scheduler.getJobKeys(
GroupMatcher.jobGroupEquals(groupName));
for (JobKey jobKey : jobKeys) {
SchedulerResponse schedulerResponse = getScheduledJob(
scheduler, jobKey);
if ((schedulerResponse != null) &&
((storageType == null) ||
(storageType == schedulerResponse.getStorageType()))) {
schedulerResponses.add(schedulerResponse);
}
}
return schedulerResponses;
}
protected Scheduler getScheduler(StorageType storageType) {
if (storageType == StorageType.PERSISTED) {
return _persistedScheduler;
}
else {
return _memoryScheduler;
}
}
protected StorageType getStorageType(String groupName) {
int pos = groupName.indexOf(CharPool.POUND);
String storageTypeString = groupName.substring(0, pos);
return StorageType.valueOf(storageTypeString);
}
protected Scheduler initializeScheduler(
String propertiesPrefix, boolean useQuartzCluster)
throws Exception {
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
Properties properties = _props.getProperties(propertiesPrefix, true);
if (useQuartzCluster) {
DB db = DBManagerUtil.getDB();
DBType dbType = db.getDBType();
if (dbType == DBType.SQLSERVER) {
String lockHandlerClassName = properties.getProperty(
"org.quartz.jobStore.lockHandler.class");
if (Validator.isNull(lockHandlerClassName)) {
properties.setProperty(
"org.quartz.jobStore.lockHandler.class",
UpdateLockRowSemaphore.class.getName());
}
}
if (GetterUtil.getBoolean(
_props.get(PropsKeys.CLUSTER_LINK_ENABLED))) {
if (dbType == DBType.HYPERSONIC) {
_log.error("Unable to cluster scheduler on Hypersonic");
}
else {
properties.put(
"org.quartz.jobStore.isClustered",
Boolean.TRUE.toString());
}
}
}
schedulerFactory.initialize(properties);
return schedulerFactory.getScheduler();
}
protected void initJobState() throws Exception {
List<String> groupNames = _persistedScheduler.getJobGroupNames();
for (String groupName : groupNames) {
Set<JobKey> jobkeys = _persistedScheduler.getJobKeys(
GroupMatcher.jobGroupEquals(groupName));
for (JobKey jobKey : jobkeys) {
Trigger trigger = _persistedScheduler.getTrigger(
new TriggerKey(jobKey.getName(), jobKey.getGroup()));
if (trigger != null) {
continue;
}
JobDetail jobDetail = _persistedScheduler.getJobDetail(jobKey);
JobDataMap jobDataMap = jobDetail.getJobDataMap();
Message message = getMessage(jobDataMap);
if (_schedulerEngineHelper != null) {
_schedulerEngineHelper.auditSchedulerJobs(
message, TriggerState.EXPIRED);
}
_persistedScheduler.deleteJob(jobKey);
}
}
}
protected void schedule(
Scheduler scheduler, StorageType storageType, Trigger trigger,
String description, String destinationName, Message message)
throws Exception {
if (_jsonFactory == null) {
throw new IllegalStateException("JSON factory not initialized");
}
try {
JobBuilder jobBuilder = JobBuilder.newJob(MessageSenderJob.class);
jobBuilder.withIdentity(trigger.getJobKey());
jobBuilder.storeDurably();
JobDetail jobDetail = jobBuilder.build();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
jobDataMap.put(SchedulerEngine.DESCRIPTION, description);
jobDataMap.put(SchedulerEngine.DESTINATION_NAME, destinationName);
jobDataMap.put(
SchedulerEngine.MESSAGE, _jsonFactory.serialize(message));
jobDataMap.put(
SchedulerEngine.STORAGE_TYPE, storageType.toString());
JobState jobState = new JobState(
TriggerState.NORMAL,
message.getInteger(SchedulerEngine.EXCEPTIONS_MAX_SIZE));
jobDataMap.put(
SchedulerEngine.JOB_STATE,
JobStateSerializeUtil.serialize(jobState));
synchronized (this) {
scheduler.deleteJob(trigger.getJobKey());
scheduler.scheduleJob(jobDetail, trigger);
}
}
catch (ObjectAlreadyExistsException oaee) {
if (_log.isInfoEnabled()) {
_log.info("Message is already scheduled");
}
}
}
@Reference(
cardinality = ReferenceCardinality.OPTIONAL,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY
)
protected void setJsonFactory(JSONFactory jsonFactory) {
_jsonFactory = jsonFactory;
}
@Reference(unbind = "-")
protected void setMessageBus(MessageBus messageBus) {
_messageBus = messageBus;
}
@Reference(
cardinality = ReferenceCardinality.OPTIONAL,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY
)
protected void setPortletLocalService(
PortletLocalService portletLocalService) {
_portletLocalService = portletLocalService;
}
@Reference(unbind = "-")
protected void setProps(Props props) {
_props = props;
_descriptionMaxLength = GetterUtil.getInteger(
_props.get(PropsKeys.SCHEDULER_DESCRIPTION_MAX_LENGTH), 120);
_groupNameMaxLength = GetterUtil.getInteger(
_props.get(PropsKeys.SCHEDULER_GROUP_NAME_MAX_LENGTH), 80);
_jobNameMaxLength = GetterUtil.getInteger(
_props.get(PropsKeys.SCHEDULER_JOB_NAME_MAX_LENGTH), 80);
}
@Reference(unbind = "-")
protected void setQuartzTriggerFactory(
QuartzTriggerFactory quartzTriggerFactory) {
_quartzTriggerFactory = quartzTriggerFactory;
}
@Reference(
target = "(&(release.bundle.symbolic.name=com.liferay.portal.scheduler.quartz)(release.schema.version=1.0.0))",
unbind = "-"
)
protected void setRelease(Release release) {
}
@Reference(
cardinality = ReferenceCardinality.OPTIONAL,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY
)
protected void setSchedulerEngineHelper(
SchedulerEngineHelper schedulerEngineHelper) {
_schedulerEngineHelper = schedulerEngineHelper;
}
protected void unschedule(Scheduler scheduler, JobKey jobKey)
throws Exception {
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
TriggerKey triggerKey = new TriggerKey(
jobKey.getName(), jobKey.getGroup());
if (jobDetail == null) {
return;
}
JobDataMap jobDataMap = jobDetail.getJobDataMap();
JobState jobState = getJobState(jobDataMap);
Trigger trigger = scheduler.getTrigger(triggerKey);
if (trigger == null) {
return;
}
jobState.setTriggerDate(SchedulerEngine.END_TIME, new Date());
jobState.setTriggerDate(
SchedulerEngine.FINAL_FIRE_TIME, trigger.getPreviousFireTime());
jobState.setTriggerDate(SchedulerEngine.NEXT_FIRE_TIME, null);
jobState.setTriggerDate(
SchedulerEngine.PREVIOUS_FIRE_TIME, trigger.getPreviousFireTime());
jobState.setTriggerDate(
SchedulerEngine.START_TIME, trigger.getStartTime());
jobState.setTriggerState(TriggerState.UNSCHEDULED);
jobState.clearExceptions();
jobDataMap.put(
SchedulerEngine.JOB_STATE,
JobStateSerializeUtil.serialize(jobState));
scheduler.unscheduleJob(triggerKey);
scheduler.addJob(jobDetail, true);
}
protected void unsetJsonFactory(JSONFactory jsonFactory) {
_jsonFactory = null;
}
protected void unsetPortletLocalService(
PortletLocalService portletLocalService) {
_portletLocalService = null;
}
protected void unsetSchedulerEngineHelper(
SchedulerEngineHelper schedulerEngineHelper) {
_schedulerEngineHelper = null;
}
protected void update(
Scheduler scheduler,
com.liferay.portal.kernel.scheduler.Trigger trigger,
StorageType storageType)
throws Exception {
Trigger quartzTrigger = (Trigger)trigger.getWrappedTrigger();
if (quartzTrigger == null) {
return;
}
TriggerKey triggerKey = quartzTrigger.getKey();
if (scheduler.getTrigger(triggerKey) != null) {
scheduler.rescheduleJob(triggerKey, quartzTrigger);
}
else {
JobKey jobKey = quartzTrigger.getJobKey();
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail == null) {
return;
}
synchronized (this) {
scheduler.deleteJob(jobKey);
scheduler.scheduleJob(jobDetail, quartzTrigger);
}
updateJobState(scheduler, jobKey, TriggerState.NORMAL, true);
}
}
protected void updateJobState(
Scheduler scheduler, JobKey jobKey, TriggerState triggerState,
boolean suppressError)
throws Exception {
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail == null) {
return;
}
JobDataMap jobDataMap = jobDetail.getJobDataMap();
JobState jobState = getJobState(jobDataMap);
if (triggerState != null) {
jobState.setTriggerState(triggerState);
}
if (suppressError) {
jobState.clearExceptions();
}
jobDataMap.put(
SchedulerEngine.JOB_STATE,
JobStateSerializeUtil.serialize(jobState));
scheduler.addJob(jobDetail, true);
}
private static final Log _log = LogFactoryUtil.getLog(
QuartzSchedulerEngine.class);
private int _descriptionMaxLength;
private int _groupNameMaxLength;
private int _jobNameMaxLength;
private JSONFactory _jsonFactory;
private Scheduler _memoryScheduler;
private MessageBus _messageBus;
private Scheduler _persistedScheduler;
private PortletLocalService _portletLocalService;
private Props _props;
private QuartzTriggerFactory _quartzTriggerFactory;
private volatile boolean _schedulerEngineEnabled;
private SchedulerEngineHelper _schedulerEngineHelper;
}