modules/core/domain/src/main/java/org/rhq/core/domain/common/JobTrigger.java | 298 ++++++++++ modules/core/domain/src/main/java/org/rhq/core/domain/common/Trigger.java | 298 ---------- modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java | 10 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java | 11 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleCompositeDataSource.java | 74 -- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleDataSource.java | 115 +++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleListView.java | 17 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java | 10 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleDataSource.java | 68 ++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleListView.java | 52 + modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java | 2 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java | 27 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java | 90 ++- 13 files changed, 680 insertions(+), 392 deletions(-)
New commits: commit c761fd50323d94e0a4d717ef885464c86959dfc8 Author: Ian Springer ian.springer@redhat.com Date: Thu Dec 16 19:55:54 2010 -0500
first rough cut of GWT-based resource Operations>Schedule subtab
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/common/JobTrigger.java b/modules/core/domain/src/main/java/org/rhq/core/domain/common/JobTrigger.java new file mode 100644 index 0000000..b3a8b48 --- /dev/null +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/common/JobTrigger.java @@ -0,0 +1,298 @@ +/* + * RHQ Management Platform + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.core.domain.common; + +import java.io.Serializable; +import java.util.Date; + +/** + * Indicates when a particular job (e.g. invocation of an RHQ Agent plugin operation) should execute. + * Note, all constructors of this class are private - the create*Trigger() static factory methods + * must be used to create instances. + * + * @author Ian Springer + */ +public class JobTrigger implements Serializable { + + private static final long serialVersionUID = 1L; + + // Together, the startType, recurrenceType, and endType define what type of trigger this is. + // For the remaining fields in this class, only those that apply to the trigger's type will have non-null values. + private StartType startType; + private RecurrenceType recurrenceType; + // Note, this field will be null when recurrenceType=NONE, since it's not applicable in that case. + private EndType endType; + + // Fields used by startType=DATETIME triggers + private Date startDate; + + // Fields used by recurrenceType=REPEAT_INTERVAL triggers + private Long repeatInterval; + // endDate and repeatCount are mutually exclusive - only one can have a non-null value; + // if both are null, the repetition is indefinite. + private Date endDate; + private Integer repeatCount; + + // Fields used by recurrenceType=CRON_EXPRESSION triggers + private String cronExpression; + + public enum StartType { + /** + * Start the initial run now. + */ + NOW, + /** + * Start the initial run at a specified date-time in the future. + */ + DATETIME; + } + + public enum RecurrenceType { + /** + * No recurrence - just run once. + */ + NONE, + /** + * Run every n seconds, starting at the start time of the initial run. + */ + REPEAT_INTERVAL, + /** + * Run on a schedule based on the specified cron expression. The expression must follow + * <a href="http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html">Quartz + * cron expression syntax</a>, which is a bit different than Unix cron expression syntax. + */ + CRON_EXPRESSION; + } + + public enum EndType { + /** + * No end - recurrence is indefinite. + */ + NEVER, + /** + * End recurrence at a specified date/time in the future. + */ + DATETIME, + /** + * End recurrence after n repetitions. + */ + REPEAT_COUNT; + } + + public StartType getStartType() { + return startType; + } + + public EndType getEndType() { + return endType; + } + + public RecurrenceType getRecurrenceType() { + return recurrenceType; + } + + public Date getStartDate() { + return startDate; + } + + public Long getRepeatInterval() { + return repeatInterval; + } + + public String getCronExpression() { + return cronExpression; + } + + public Date getEndDate() { + return endDate; + } + + public Integer getRepeatCount() { + return repeatCount; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Trigger"); + sb.append("[cronExpression='").append(cronExpression).append('''); + sb.append(", startType=").append(startType); + sb.append(", recurrenceType=").append(recurrenceType); + sb.append(", endType=").append(endType); + sb.append(", startDate=").append(startDate); + sb.append(", repeatInterval=").append(repeatInterval); + sb.append(", endDate=").append(endDate); + sb.append(", repeatCount=").append(repeatCount); + sb.append(']'); + return sb.toString(); + } + + /** + * Create a trigger that will run now, once. + * + * @return a trigger that will run now, once + */ + public static JobTrigger createNowTrigger() { + return new JobTrigger(); + } + + /** + * Create a trigger that will run now and repeat on interval indefinitely. + * + * @return a trigger that will run now and repeat on interval indefinitely + */ + public static JobTrigger createNowAndRepeatTrigger(long repeatInterval) { + return new JobTrigger(repeatInterval); + } + + /** + * Create a trigger that will run now and repeat on interval until end date/time. + * + * @return a trigger that will run now and repeat on interval until end date/time + */ + public static JobTrigger createNowAndRepeatTrigger(long repeatInterval, Date endDate) { + return new JobTrigger(repeatInterval, endDate); + } + + /** + * Create a trigger that will run now and repeat on interval n times. + * + * @return a trigger that will run now and repeat on interval n times + */ + public static JobTrigger createNowAndRepeatTrigger(long repeatInterval, int repeatCount) { + return new JobTrigger(repeatInterval, repeatCount); + } + + /** + * Create a trigger that will run at specified date/time, once. + * + * @return a trigger that will run at specified date/time, once + */ + public static JobTrigger createLaterTrigger(Date startDate) { + return new JobTrigger(startDate); + } + + /** + * Create a trigger that will run at specified date/time and then repeat on interval indefinitely. + * + * @return a trigger that will run at specified date/time and then repeat on interval indefinitely + */ + public static JobTrigger createLaterAndRepeatTrigger(Date startDate, long repeatInterval) { + return new JobTrigger(startDate, repeatInterval); + } + + /** + * Create a trigger that will run at specified date/time and then repeat on interval until end date/time. + * + * @return a trigger that will run at specified date/time and then repeat on interval until end date/time + */ + public static JobTrigger createLaterAndRepeatTrigger(Date startDate, long repeatInterval, Date endDate) { + return new JobTrigger(startDate, repeatInterval, endDate); + } + + /** + * Create a trigger that will run at specified date/time and then repeat on interval n times. + * + * @return a trigger that will run at specified date/time and then repeat on interval n times + */ + public static JobTrigger createLaterAndRepeatTrigger(Date startDate, long repeatInterval, int repeatCount) { + return new JobTrigger(startDate, repeatInterval, repeatCount); + } + + /** + * Create a trigger that will run on the schedule specified by a cron expression. The expression must follow + * <a href="http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html">Quartz + * cron expression syntax</a>, which is a bit different than Unix cron expression syntax. + * + * @return a trigger that will run on the schedule specified by a cron expression + */ + public static JobTrigger createCronTrigger(String cronExpression) { + return new JobTrigger(cronExpression); + } + + + private JobTrigger(StartType startType, RecurrenceType recurrenceType, EndType endType) { + this.startType = startType; + this.recurrenceType = recurrenceType; + this.endType = endType; + } + + // run now, once + private JobTrigger() { + this(StartType.NOW, RecurrenceType.NONE, null); + } + + // run now and repeat on interval indefinitely + private JobTrigger(long repeatInterval) { + this(StartType.NOW, RecurrenceType.REPEAT_INTERVAL, EndType.REPEAT_COUNT); + this.repeatInterval = repeatInterval; + } + + // run now and repeat on interval until end date/time + private JobTrigger(long repeatInterval, Date endDate) { + this(StartType.NOW, RecurrenceType.REPEAT_INTERVAL, EndType.DATETIME); + this.repeatInterval = repeatInterval; + this.endDate = endDate; + } + + // run now and repeat on interval n times + private JobTrigger(long repeatInterval, int repeatCount) { + this(StartType.NOW, RecurrenceType.REPEAT_INTERVAL, EndType.REPEAT_COUNT); + this.repeatInterval = repeatInterval; + this.repeatCount = repeatCount; + } + + // run at specified date/time, once + private JobTrigger(Date startDate) { + this(StartType.DATETIME, RecurrenceType.NONE, EndType.REPEAT_COUNT); + this.startDate = startDate; + this.repeatCount = 1; + } + + // run at specified date/time and then repeat on interval indefinitely + private JobTrigger(Date startDate, long repeatInterval) { + this(StartType.DATETIME, RecurrenceType.REPEAT_INTERVAL, EndType.NEVER); + this.startDate = startDate; + this.repeatInterval = repeatInterval; + } + + // run at specified date/time and then repeat on interval until end date/time + private JobTrigger(Date startDate, long repeatInterval, Date endDate) { + this(StartType.DATETIME, RecurrenceType.REPEAT_INTERVAL, EndType.DATETIME); + this.startDate = startDate; + this.repeatInterval = repeatInterval; + this.endDate = endDate; + } + + // run at specified date/time and then repeat on interval n times + private JobTrigger(Date startDate, long repeatInterval, int repeatCount) { + this(StartType.DATETIME, RecurrenceType.REPEAT_INTERVAL, EndType.REPEAT_COUNT); + this.startDate = startDate; + this.repeatInterval = repeatInterval; + this.repeatCount = repeatCount; + } + + // run on the schedule specified by cron expression + private JobTrigger(String cronExpression) { + this(StartType.NOW, RecurrenceType.CRON_EXPRESSION, EndType.NEVER); + this.cronExpression = cronExpression; + } + +} diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/common/Trigger.java b/modules/core/domain/src/main/java/org/rhq/core/domain/common/Trigger.java deleted file mode 100644 index da58047..0000000 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/common/Trigger.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * RHQ Management Platform - * Copyright 2010, Red Hat Middleware LLC, and individual contributors - * as indicated by the @author tags. See the copyright.txt file in the - * distribution for a full listing of individual contributors. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -package org.rhq.core.domain.common; - -import java.io.Serializable; -import java.util.Date; - -/** - * Indicates when a particular job (e.g. invocation of an RHQ Agent plugin operation) should execute. - * Note, all constructors of this class are private - the create*Trigger() static factory methods - * must be used to create instances. - * - * @author Ian Springer - */ -public class Trigger implements Serializable { - - private static final long serialVersionUID = 1L; - - // Together, the startType, recurrenceType, and endType define what type of trigger this is. - // For the remaining fields in this class, only those that apply to the trigger's type will have non-null values. - private StartType startType; - private RecurrenceType recurrenceType; - // Note, this field will be null when recurrenceType=NONE, since it's not applicable in that case. - private EndType endType; - - // Fields used by startType=DATETIME triggers - private Date startDate; - - // Fields used by recurrenceType=REPEAT_INTERVAL triggers - private Long repeatInterval; - // endDate and repeatCount are mutually exclusive - only one can have a non-null value; - // if both are null, the repetition is indefinite. - private Date endDate; - private Integer repeatCount; - - // Fields used by recurrenceType=CRON_EXPRESSION triggers - private String cronExpression; - - public enum StartType { - /** - * Start the initial run now. - */ - NOW, - /** - * Start the initial run at a specified date-time in the future. - */ - DATETIME; - } - - public enum RecurrenceType { - /** - * No recurrence - just run once. - */ - NONE, - /** - * Run every n seconds, starting at the start time of the initial run. - */ - REPEAT_INTERVAL, - /** - * Run on a schedule based on the specified cron expression. The expression must follow - * <a href="http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html">Quartz - * cron expression syntax</a>, which is a bit different than Unix cron expression syntax. - */ - CRON_EXPRESSION; - } - - public enum EndType { - /** - * No end - recurrence is indefinite. - */ - NEVER, - /** - * End recurrence at a specified date/time in the future. - */ - DATETIME, - /** - * End recurrence after n repetitions. - */ - REPEAT_COUNT; - } - - public StartType getStartType() { - return startType; - } - - public EndType getEndType() { - return endType; - } - - public RecurrenceType getRecurrenceType() { - return recurrenceType; - } - - public Date getStartDate() { - return startDate; - } - - public Long getRepeatInterval() { - return repeatInterval; - } - - public String getCronExpression() { - return cronExpression; - } - - public Date getEndDate() { - return endDate; - } - - public Integer getRepeatCount() { - return repeatCount; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append("Trigger"); - sb.append("[cronExpression='").append(cronExpression).append('''); - sb.append(", startType=").append(startType); - sb.append(", recurrenceType=").append(recurrenceType); - sb.append(", endType=").append(endType); - sb.append(", startDate=").append(startDate); - sb.append(", repeatInterval=").append(repeatInterval); - sb.append(", endDate=").append(endDate); - sb.append(", repeatCount=").append(repeatCount); - sb.append(']'); - return sb.toString(); - } - - /** - * Create a trigger that will run now, once. - * - * @return a trigger that will run now, once - */ - public static Trigger createNowTrigger() { - return new Trigger(); - } - - /** - * Create a trigger that will run now and repeat on interval indefinitely. - * - * @return a trigger that will run now and repeat on interval indefinitely - */ - public static Trigger createNowAndRepeatTrigger(long repeatInterval) { - return new Trigger(repeatInterval); - } - - /** - * Create a trigger that will run now and repeat on interval until end date/time. - * - * @return a trigger that will run now and repeat on interval until end date/time - */ - public static Trigger createNowAndRepeatTrigger(long repeatInterval, Date endDate) { - return new Trigger(repeatInterval, endDate); - } - - /** - * Create a trigger that will run now and repeat on interval n times. - * - * @return a trigger that will run now and repeat on interval n times - */ - public static Trigger createNowAndRepeatTrigger(long repeatInterval, int repeatCount) { - return new Trigger(repeatInterval, repeatCount); - } - - /** - * Create a trigger that will run at specified date/time, once. - * - * @return a trigger that will run at specified date/time, once - */ - public static Trigger createLaterTrigger(Date startDate) { - return new Trigger(startDate); - } - - /** - * Create a trigger that will run at specified date/time and then repeat on interval indefinitely. - * - * @return a trigger that will run at specified date/time and then repeat on interval indefinitely - */ - public static Trigger createLaterAndRepeatTrigger(Date startDate, long repeatInterval) { - return new Trigger(startDate, repeatInterval); - } - - /** - * Create a trigger that will run at specified date/time and then repeat on interval until end date/time. - * - * @return a trigger that will run at specified date/time and then repeat on interval until end date/time - */ - public static Trigger createLaterAndRepeatTrigger(Date startDate, long repeatInterval, Date endDate) { - return new Trigger(startDate, repeatInterval, endDate); - } - - /** - * Create a trigger that will run at specified date/time and then repeat on interval n times. - * - * @return a trigger that will run at specified date/time and then repeat on interval n times - */ - public static Trigger createLaterAndRepeatTrigger(Date startDate, long repeatInterval, int repeatCount) { - return new Trigger(startDate, repeatInterval, repeatCount); - } - - /** - * Create a trigger that will run on the schedule specified by a cron expression. The expression must follow - * <a href="http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html">Quartz - * cron expression syntax</a>, which is a bit different than Unix cron expression syntax. - * - * @return a trigger that will run on the schedule specified by a cron expression - */ - public static Trigger createCronTrigger(String cronExpression) { - return new Trigger(cronExpression); - } - - - private Trigger(StartType startType, RecurrenceType recurrenceType, EndType endType) { - this.startType = startType; - this.recurrenceType = recurrenceType; - this.endType = endType; - } - - // run now, once - private Trigger() { - this(StartType.NOW, RecurrenceType.NONE, null); - } - - // run now and repeat on interval indefinitely - private Trigger(long repeatInterval) { - this(StartType.NOW, RecurrenceType.REPEAT_INTERVAL, EndType.REPEAT_COUNT); - this.repeatInterval = repeatInterval; - } - - // run now and repeat on interval until end date/time - private Trigger(long repeatInterval, Date endDate) { - this(StartType.NOW, RecurrenceType.REPEAT_INTERVAL, EndType.DATETIME); - this.repeatInterval = repeatInterval; - this.endDate = endDate; - } - - // run now and repeat on interval n times - private Trigger(long repeatInterval, int repeatCount) { - this(StartType.NOW, RecurrenceType.REPEAT_INTERVAL, EndType.REPEAT_COUNT); - this.repeatInterval = repeatInterval; - this.repeatCount = repeatCount; - } - - // run at specified date/time, once - private Trigger(Date startDate) { - this(StartType.DATETIME, RecurrenceType.NONE, EndType.REPEAT_COUNT); - this.startDate = startDate; - this.repeatCount = 1; - } - - // run at specified date/time and then repeat on interval indefinitely - private Trigger(Date startDate, long repeatInterval) { - this(StartType.DATETIME, RecurrenceType.REPEAT_INTERVAL, EndType.NEVER); - this.startDate = startDate; - this.repeatInterval = repeatInterval; - } - - // run at specified date/time and then repeat on interval until end date/time - private Trigger(Date startDate, long repeatInterval, Date endDate) { - this(StartType.DATETIME, RecurrenceType.REPEAT_INTERVAL, EndType.DATETIME); - this.startDate = startDate; - this.repeatInterval = repeatInterval; - this.endDate = endDate; - } - - // run at specified date/time and then repeat on interval n times - private Trigger(Date startDate, long repeatInterval, int repeatCount) { - this(StartType.DATETIME, RecurrenceType.REPEAT_INTERVAL, EndType.REPEAT_COUNT); - this.startDate = startDate; - this.repeatInterval = repeatInterval; - this.repeatCount = repeatCount; - } - - // run on the schedule specified by cron expression - private Trigger(String cronExpression) { - this(StartType.NOW, RecurrenceType.CRON_EXPRESSION, EndType.NEVER); - this.cronExpression = cronExpression; - } - -} diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java index f92f3d0..c638b31 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java @@ -26,6 +26,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement;
import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.common.JobTrigger; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.operation.HistoryJobId; import org.rhq.core.domain.operation.JobId; @@ -47,6 +48,7 @@ public abstract class OperationSchedule implements Serializable { private Configuration parameters; private Subject subject; private String description; + private JobTrigger jobTrigger;
public OperationSchedule() { } @@ -124,6 +126,14 @@ public abstract class OperationSchedule implements Serializable { this.description = description; }
+ public JobTrigger getJobTrigger() { + return jobTrigger; + } + + public void setJobTrigger(JobTrigger jobTrigger) { + this.jobTrigger = jobTrigger; + } + /** * The single job ID which identifies the operation. It can later be parsed via {@link JobId#JobId(String)}. Note * that this job ID only identifies the scheduled operation; it does not identify any specific invocation of that diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java index 58d02ee..badd227 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java @@ -27,10 +27,13 @@ import org.rhq.core.domain.criteria.GroupOperationHistoryCriteria; import org.rhq.core.domain.criteria.ResourceOperationHistoryCriteria; import org.rhq.core.domain.operation.GroupOperationHistory; import org.rhq.core.domain.operation.ResourceOperationHistory; +import org.rhq.core.domain.operation.bean.GroupOperationSchedule; +import org.rhq.core.domain.operation.bean.ResourceOperationSchedule; import org.rhq.core.domain.operation.composite.ResourceOperationLastCompletedComposite; import org.rhq.core.domain.operation.composite.ResourceOperationScheduleComposite; import org.rhq.core.domain.resource.composite.DisambiguationReport; import org.rhq.core.domain.util.PageList; +import org.rhq.core.util.exception.ThrowableUtil;
/** * @author Greg Hinkle @@ -46,10 +49,14 @@ public interface OperationGWTService extends RemoteService {
List<DisambiguationReport<ResourceOperationScheduleComposite>> findScheduledOperations(int pageSize);
- public void invokeResourceOperation(int resourceId, String operationName, Configuration parameters, + void invokeResourceOperation(int resourceId, String operationName, Configuration parameters, String description, int timeout) throws RuntimeException;
- public void scheduleResourceOperation(int resourceId, String operationName, Configuration parameters, + void scheduleResourceOperation(int resourceId, String operationName, Configuration parameters, String description, int timeout, String cronString) throws RuntimeException;
+ List<ResourceOperationSchedule> findScheduledResourceOperations(int resourceId) throws RuntimeException; + + List<GroupOperationSchedule> findScheduledGroupOperations(int groupId) throws RuntimeException; + } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleCompositeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleCompositeDataSource.java deleted file mode 100644 index 88df113..0000000 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleCompositeDataSource.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * RHQ Management Platform - * Copyright 2010, Red Hat Middleware LLC, and individual contributors - * as indicated by the @author tags. See the copyright.txt file in the - * distribution for a full listing of individual contributors. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -package org.rhq.enterprise.gui.coregui.client.inventory.common.detail.operation.schedule; - -import java.util.List; - -import com.smartgwt.client.data.DataSourceField; -import com.smartgwt.client.data.fields.DataSourceIntegerField; -import com.smartgwt.client.data.fields.DataSourceTextField; - -import org.rhq.core.domain.operation.composite.OperationScheduleComposite; -import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; -import org.rhq.enterprise.gui.coregui.client.gwt.OperationGWTServiceAsync; -import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; - -/** - * @author Ian Springer - */ -public abstract class OperationScheduleCompositeDataSource extends RPCDataSource<OperationScheduleComposite> { - - public static abstract class Field { - - public static final String OPERATION_JOB_ID = "operationJobId"; - public static final String OPERATION_NAME = "operationName"; - public static final String OPERATION_NEXT_FIRE_TIME = "operationNextFireTime"; - } - - protected OperationGWTServiceAsync operationService = GWTServiceLookup.getOperationService(); - - public OperationScheduleCompositeDataSource() { - super(); - List<DataSourceField> fields = addDataSourceFields(); - addFields(fields); - } - - @Override - protected List<DataSourceField> addDataSourceFields() { - List<DataSourceField> fields = super.addDataSourceFields(); - - // TODO: i18n - DataSourceIntegerField idField = new DataSourceIntegerField(Field.OPERATION_JOB_ID, "ID"); - idField.setPrimaryKey(true); - idField.setCanEdit(false); - fields.add(idField); - - DataSourceTextField nameField = createTextField(Field.OPERATION_NAME, MSG.common_title_name(), 3, 100, true); - fields.add(nameField); - - // TODO: i18n - DataSourceTextField nextFireTimeField = createTextField(Field.OPERATION_NEXT_FIRE_TIME, "Next Fire Time", null, - 100, false); - fields.add(nextFireTimeField); - - return fields; - } - -} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleDataSource.java new file mode 100644 index 0000000..65fe51f --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleDataSource.java @@ -0,0 +1,115 @@ +/* + * RHQ Management Platform + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client.inventory.common.detail.operation.schedule; + +import java.util.List; + +import com.smartgwt.client.data.DataSourceField; +import com.smartgwt.client.data.Record; +import com.smartgwt.client.data.fields.DataSourceTextField; +import com.smartgwt.client.widgets.grid.ListGridRecord; + +import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.common.JobTrigger; +import org.rhq.core.domain.configuration.Configuration; +import org.rhq.core.domain.operation.bean.OperationSchedule; +import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; +import org.rhq.enterprise.gui.coregui.client.gwt.OperationGWTServiceAsync; +import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; + +/** + * @author Ian Springer + */ +public abstract class OperationScheduleDataSource<T extends OperationSchedule> extends RPCDataSource<T> { + + public static abstract class Field { + public static final String JOB_NAME = "jobName"; + public static final String JOB_GROUP = "jobGroup"; + public static final String OPERATION_NAME = "operationName"; + public static final String OPERATION_DISPLAY_NAME = "operationDisplayName"; + public static final String PARAMETERS = "parameters"; + public static final String SUBJECT = "subject"; + public static final String DESCRIPTION = "description"; + public static final String JOB_TRIGGER = "jobTrigger"; + } + + protected OperationGWTServiceAsync operationService = GWTServiceLookup.getOperationService(); + + public OperationScheduleDataSource() { + super(); + List<DataSourceField> fields = addDataSourceFields(); + addFields(fields); + } + + // TODO: i18n + @Override + protected List<DataSourceField> addDataSourceFields() { + List<DataSourceField> fields = super.addDataSourceFields(); + + DataSourceTextField operationDisplayNameField = createTextField(Field.OPERATION_DISPLAY_NAME, "Operation", null, 100, true); + fields.add(operationDisplayNameField); + + DataSourceTextField subjectField = createTextField(Field.SUBJECT, "Owner", null, 100, true); + fields.add(subjectField); + + DataSourceTextField descriptionField = createTextField(Field.DESCRIPTION, "Description", null, 100, true); + fields.add(descriptionField); + + DataSourceTextField jobTriggerField = createTextField(Field.JOB_TRIGGER, "Schedule", null, 100, true); + fields.add(jobTriggerField); + + return fields; + } + + protected abstract T createOperationSchedule(); + + @Override + public T copyValues(Record from) { + T to = createOperationSchedule(); + + to.setJobName(from.getAttribute(Field.JOB_NAME)); + to.setJobGroup(from.getAttribute(Field.JOB_GROUP)); + to.setJobTrigger((JobTrigger)from.getAttributeAsObject(Field.JOB_TRIGGER)); + to.setDescription(from.getAttribute(Field.DESCRIPTION)); + to.setOperationDisplayName(from.getAttribute(Field.OPERATION_DISPLAY_NAME)); + to.setOperationName(from.getAttribute(Field.OPERATION_NAME)); + to.setParameters((Configuration)from.getAttributeAsObject(Field.PARAMETERS)); + to.setSubject((Subject)from.getAttributeAsObject(Field.SUBJECT)); + + return to; + } + + @Override + public ListGridRecord copyValues(T from) { + ListGridRecord to = new ListGridRecord(); + + to.setAttribute(Field.JOB_NAME, from.getJobName()); + to.setAttribute(Field.JOB_GROUP, from.getJobGroup()); + to.setAttribute(Field.JOB_TRIGGER, from.getJobTrigger()); + to.setAttribute(Field.OPERATION_DISPLAY_NAME, from.getOperationDisplayName()); + to.setAttribute(Field.OPERATION_NAME, from.getOperationName()); + to.setAttribute(Field.SUBJECT, from.getSubject()); + to.setAttribute(Field.DESCRIPTION, from.getDescription()); + to.setAttribute(Field.PARAMETERS, from.getParameters()); + + return to; + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleListView.java index 29d0136..d658acc 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleListView.java @@ -28,15 +28,12 @@ import org.rhq.enterprise.gui.coregui.client.components.table.TableSection; /** * @author Ian Springer */ -public abstract class OperationScheduleListView extends TableSection<OperationScheduleCompositeDataSource> { +public abstract class OperationScheduleListView extends TableSection<OperationScheduleDataSource> {
- private static final String HEADER_ICON = "subsystems/control/Operation_24.png"; - - public OperationScheduleListView(String locatorId, OperationScheduleCompositeDataSource dataSource, String title) { + public OperationScheduleListView(String locatorId, OperationScheduleDataSource dataSource, String title) { super(locatorId, title);
setDataSource(dataSource); - setHeaderIcon(HEADER_ICON); }
protected abstract boolean hasControlPermission(); @@ -45,11 +42,15 @@ public abstract class OperationScheduleListView extends TableSection<OperationSc protected void configureTable() { super.configureTable();
- ListGridField nameField = new ListGridField(OperationScheduleCompositeDataSource.Field.OPERATION_NAME, 150); + ListGridField operationField = new ListGridField(OperationScheduleDataSource.Field.OPERATION_DISPLAY_NAME, 150); + + //ListGridField subjectField = new ListGridField(OperationScheduleDataSource.Field.SUBJECT, 150); + + //ListGridField jobTriggerField = new ListGridField(OperationScheduleDataSource.Field.JOB_TRIGGER, 300);
- ListGridField nextFireTimeField = new ListGridField(OperationScheduleCompositeDataSource.Field.OPERATION_NEXT_FIRE_TIME); + ListGridField descriptionField = new ListGridField(OperationScheduleDataSource.Field.DESCRIPTION);
- setListGridFields(nameField, nextFireTimeField); + setListGridFields(operationField, descriptionField);
addTableAction(extendLocatorId("New"), MSG.common_button_new(), new TableAction() { public boolean isEnabled(ListGridRecord[] selection) { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java index de120f5..9cbf3e2 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java @@ -61,6 +61,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.schedules.SchedulesView; import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.traits.TraitsView; import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.history.ResourceOperationHistoryListView; +import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.schedule.ResourceOperationScheduleListView; import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.summary.ActivityView; import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository; import org.rhq.enterprise.gui.coregui.client.util.message.Message; @@ -243,7 +244,7 @@ public class ResourceDetailView extends AbstractTwoLevelTabSetView<ResourceCompo updateAlertsTabContent(resourceComposite); updateMonitoringTabContent(resource, facets); updateEventsTabContent(resourceComposite, facets); - updateOperationsTabContent(resource, facets); + updateOperationsTabContent(facets); updateConfigurationTabContent(resourceComposite, resource, resourcePermissions, facets); updateContentTabContent(resource, facets);
@@ -334,7 +335,7 @@ public class ResourceDetailView extends AbstractTwoLevelTabSetView<ResourceCompo } }
- private void updateOperationsTabContent(Resource resource, Set<ResourceTypeFacet> facets) { + private void updateOperationsTabContent(Set<ResourceTypeFacet> facets) { if (updateTab(this.operationsTab, facets.contains(ResourceTypeFacet.OPERATION), true)) { // comment out GWT-based operation history until... // 1) user can delete history if they possess the appropriate permissions @@ -342,11 +343,12 @@ public class ResourceDetailView extends AbstractTwoLevelTabSetView<ResourceCompo // 3) operation arguments/results become read-only configuration data in the history details pop-up // 4) user can navigate to the group operation that spawned this resource operation history, if appropriate // note: enabled operation execution/schedules from left-nav, if it doesn't already exist + updateSubTab(this.operationsTab, this.operationsHistory, new ResourceOperationHistoryListView(operationsTab .extendLocatorId("HistoryView"), this.resourceComposite), true, true);
- updateSubTab(this.operationsTab, this.operationsSchedule, new FullHTMLPane(this.operationsSchedule.extendLocatorId("View"), - "/rhq/resource/operation/resourceOperationSchedules-plain.xhtml?id=" + resource.getId()), true, true); + updateSubTab(this.operationsTab, this.operationsSchedule,new ResourceOperationScheduleListView(operationsTab.extendLocatorId("SchedulesView"), this.resourceComposite), + true, true); } }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleDataSource.java new file mode 100644 index 0000000..e044f51 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleDataSource.java @@ -0,0 +1,68 @@ +/* + * RHQ Management Platform + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.schedule; + +import java.util.List; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.data.DSRequest; +import com.smartgwt.client.data.DSResponse; +import com.smartgwt.client.data.Record; + +import org.rhq.core.domain.operation.bean.ResourceOperationSchedule; +import org.rhq.core.domain.resource.Resource; +import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.operation.schedule.OperationScheduleDataSource; + +/** + * A DataSource for {@link ResourceOperationSchedule}s for a given {@link Resource}. + * + * @author Ian Springer + */ +public class ResourceOperationScheduleDataSource extends OperationScheduleDataSource<ResourceOperationSchedule> { + + private int resourceId; + + public ResourceOperationScheduleDataSource(int resourceId) { + this.resourceId = resourceId; + } + + @Override + protected ResourceOperationSchedule createOperationSchedule() { + return new ResourceOperationSchedule(); + } + + @Override + protected void executeFetch(final DSRequest request, final DSResponse response) { + operationService.findScheduledResourceOperations(this.resourceId, + new AsyncCallback<List<ResourceOperationSchedule>>() { + public void onSuccess(List<ResourceOperationSchedule> result) { + Record[] records = buildRecords(result); + response.setData(records); + processResponse(request.getRequestId(), response); + } + + public void onFailure(Throwable caught) { + throw new RuntimeException("Failed to find scheduled operations for Resource with id [" + + resourceId + "].", caught); + } + }); + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleListView.java new file mode 100644 index 0000000..03de2a6 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleListView.java @@ -0,0 +1,52 @@ +/* + * RHQ Management Platform + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.schedule; + +import com.smartgwt.client.widgets.Canvas; + +import org.rhq.core.domain.resource.composite.ResourceComposite; +import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.operation.schedule.OperationScheduleDataSource; +import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.operation.schedule.OperationScheduleListView; + +/** + * @author Ian Springer + */ +public class ResourceOperationScheduleListView extends OperationScheduleListView { + + private static final String TITLE = null; + + private ResourceComposite resourceComposite; + + public ResourceOperationScheduleListView(String locatorId, ResourceComposite resourceComposite) { + super(locatorId, new ResourceOperationScheduleDataSource(resourceComposite.getResource().getId()), TITLE); + this.resourceComposite = resourceComposite; + } + + @Override + protected boolean hasControlPermission() { + return this.resourceComposite.getResourcePermission().isControl(); + } + + @Override + public Canvas getDetailsView(int id) { + return new Canvas(); // TODO + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java index de8e667..a7bd459 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java @@ -85,7 +85,7 @@ public abstract class RPCDataSource<T> extends DataSource { }
/** - * A pattern that can be used for Datasource subclassing. Each subclass can add it's own fields prior to + * A pattern that can be used for Datasource subclassing. Each subclass can add its own fields prior to * all of the fields being added to the datasource. */ protected List<DataSourceField> addDataSourceFields() { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java index 7cef256..a51ed3f 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java @@ -27,6 +27,7 @@ import org.rhq.core.domain.criteria.GroupOperationHistoryCriteria; import org.rhq.core.domain.criteria.ResourceOperationHistoryCriteria; import org.rhq.core.domain.operation.GroupOperationHistory; import org.rhq.core.domain.operation.ResourceOperationHistory; +import org.rhq.core.domain.operation.bean.GroupOperationSchedule; import org.rhq.core.domain.operation.bean.ResourceOperationSchedule; import org.rhq.core.domain.operation.composite.ResourceOperationLastCompletedComposite; import org.rhq.core.domain.operation.composite.ResourceOperationScheduleComposite; @@ -75,7 +76,7 @@ public class OperationGWTServiceImpl extends AbstractGWTServiceImpl implements O ResourceOperationSchedule opSchedule = operationManager.scheduleResourceOperation(getSessionSubject(), resourceId, operationName, 0, 0, 0, 0, parameters, description); } catch (Exception e) { - throw new RuntimeException("Unabled to invoke operation: " + e.getMessage()); + throw new RuntimeException("Unable to invoke operation: " + e.getMessage()); } }
@@ -87,7 +88,7 @@ public class OperationGWTServiceImpl extends AbstractGWTServiceImpl implements O resourceId, operationName, parameters, ct, description);
} catch (Exception e) { - throw new RuntimeException("Unabled to schedule operation execution: " + e.getMessage()); + throw new RuntimeException("Unable to schedule operation execution: " + e.getMessage()); } }
@@ -132,6 +133,28 @@ public class OperationGWTServiceImpl extends AbstractGWTServiceImpl implements O } }
+ public List<ResourceOperationSchedule> findScheduledResourceOperations(int resourceId) throws RuntimeException { + try { + List<ResourceOperationSchedule> resourceOperationSchedules = + operationManager.findScheduledResourceOperations(getSessionSubject(), resourceId); + return SerialUtility.prepare(resourceOperationSchedules, "findScheduledResourceOperations"); + } + catch (Exception e) { + throw new RuntimeException(ThrowableUtil.getAllMessages(e)); + } + } + + public List<GroupOperationSchedule> findScheduledGroupOperations(int groupId) throws RuntimeException { + try { + List<GroupOperationSchedule> groupOperationSchedules = + operationManager.findScheduledGroupOperations(getSessionSubject(), groupId); + return SerialUtility.prepare(groupOperationSchedules, "findScheduledGroupOperations"); + } + catch (Exception e) { + throw new RuntimeException(ThrowableUtil.getAllMessages(e)); + } + } + private static final IntExtractor<ResourceOperationLastCompletedComposite> RESOURCE_OPERATION_RESOURCE_ID_EXTRACTOR = new IntExtractor<ResourceOperationLastCompletedComposite>() { public int extract(ResourceOperationLastCompletedComposite object) { return object.getResourceId(); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java index cdda16d..a1fc704 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java @@ -19,6 +19,7 @@ package org.rhq.enterprise.server.operation;
import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Set; @@ -34,6 +35,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jetbrains.annotations.Nullable; +import org.quartz.CronTrigger; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.SchedulerException; @@ -44,6 +46,7 @@ import org.rhq.core.clientapi.agent.operation.CancelResults; import org.rhq.core.clientapi.agent.operation.CancelResults.InterruptedState; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; +import org.rhq.core.domain.common.JobTrigger; import org.rhq.core.domain.common.composite.IntegerOptionItem; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertySimple; @@ -418,7 +421,7 @@ public class OperationManagerBean implements OperationManagerLocal, OperationMan return operationSchedules; }
- public ResourceOperationSchedule getResourceOperationSchedule(Subject subject, JobDetail jobDetail) { + public ResourceOperationSchedule getResourceOperationSchedule(Subject whoami, JobDetail jobDetail) { JobDataMap jobDataMap = jobDetail.getJobDataMap();
String description = jobDetail.getDescription(); @@ -433,7 +436,7 @@ public class OperationManagerBean implements OperationManagerLocal, OperationMan }
int resourceId = jobDataMap.getIntFromString(ResourceOperationJob.DATAMAP_INT_RESOURCE_ID); - Resource resource = getResourceIfAuthorized(subject, resourceId); + Resource resource = getResourceIfAuthorized(whoami, resourceId);
// note that we throw an exception if the subject does not exist! // this is by design to avoid a malicious user creating a dummy subject in the database, @@ -447,9 +450,13 @@ public class OperationManagerBean implements OperationManagerLocal, OperationMan sched.setResource(resource); sched.setOperationName(operationName); sched.setOperationDisplayName(displayName); - sched.setSubject(subjectManager.getSubjectById(subjectId)); + Subject subject = subjectManager.getSubjectById(subjectId); + sched.setSubject(subject); sched.setParameters(parameters); sched.setDescription(description); + Trigger trigger = getTriggerOfJob(jobDetail); + JobTrigger jobTrigger = convertToJobTrigger(trigger); + sched.setJobTrigger(jobTrigger);
return sched; } @@ -515,6 +522,9 @@ public class OperationManagerBean implements OperationManagerLocal, OperationMan sched.setExecutionOrder(executionOrder); sched.setDescription(description); sched.setHaltOnFailure(jobDataMap.getBooleanValueFromString(GroupOperationJob.DATAMAP_BOOL_HALT_ON_FAILURE)); + Trigger trigger = getTriggerOfJob(jobDetail); + JobTrigger jobTrigger = convertToJobTrigger(trigger); + sched.setJobTrigger(jobTrigger);
return sched; } @@ -1828,4 +1838,78 @@ public class OperationManagerBean implements OperationManagerLocal, OperationMan entityManager); return queryRunner.execute(); } + + private Trigger getTriggerOfJob(JobDetail jobDetail) { + Trigger[] triggers; + try { + triggers = scheduler.getTriggersOfJob(jobDetail.getName(), jobDetail.getGroup()); + } + catch (SchedulerException e) { + throw new RuntimeException("Failed to lookup trigger for job [" + jobDetail.getFullName() + "].", e); + } + if (triggers.length == 0) { + throw new IllegalStateException("Job [" + jobDetail.getFullName() + "] has no triggers."); + } + if (triggers.length > 1) { + throw new IllegalStateException("Job [" + jobDetail.getFullName() + "] has more than one trigger: " + + Arrays.asList(triggers)); + } + return triggers[0]; + } + + private static JobTrigger convertToJobTrigger(Trigger trigger) { + JobTrigger schedule; + if (trigger instanceof SimpleTrigger) { + SimpleTrigger simpleTrigger = (SimpleTrigger)trigger; + Date startTime = simpleTrigger.getStartTime(); + if (startTime != null) { + // later + int repeatCount = simpleTrigger.getRepeatCount(); + if (repeatCount == 0) { + // non-recurring + schedule = JobTrigger.createLaterTrigger(startTime); + } else { + // recurring + long repeatInterval = simpleTrigger.getRepeatInterval(); + if (repeatCount == SimpleTrigger.REPEAT_INDEFINITELY) { + Date endTime = simpleTrigger.getEndTime(); + if (endTime != null) { + schedule = JobTrigger.createLaterAndRepeatTrigger(startTime, repeatInterval, endTime); + } else { + schedule = JobTrigger.createLaterAndRepeatTrigger(startTime, repeatInterval); + } + } else { + schedule = JobTrigger.createLaterAndRepeatTrigger(startTime, repeatInterval, repeatCount); + } + } + } else { + // now + int repeatCount = simpleTrigger.getRepeatCount(); + if (repeatCount == 0) { + // non-recurring + schedule = JobTrigger.createNowTrigger(); + } else { + // recurring + long repeatInterval = simpleTrigger.getRepeatInterval(); + if (repeatCount == SimpleTrigger.REPEAT_INDEFINITELY) { + Date endTime = simpleTrigger.getEndTime(); + if (endTime != null) { + schedule = JobTrigger.createNowAndRepeatTrigger(repeatInterval, endTime); + } else { + schedule = JobTrigger.createNowAndRepeatTrigger(repeatInterval); + } + } else { + schedule = JobTrigger.createNowAndRepeatTrigger(repeatInterval, repeatCount); + } + } + } + } else if (trigger instanceof CronTrigger) { + CronTrigger cronTrigger = (CronTrigger)trigger; + schedule = JobTrigger.createCronTrigger(cronTrigger.getCronExpression()); + } else { + throw new IllegalStateException("Unsupported Quartz trigger type: " + trigger.getClass().getName()); + } + return schedule; + } + } \ No newline at end of file
rhq-commits@lists.fedorahosted.org