/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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 Lesser General Public License for more details. * * Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.platform.web.http.api.resources; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.APPLICATION_XML; import static javax.ws.rs.core.MediaType.TEXT_PLAIN; import static javax.ws.rs.core.Response.Status.FORBIDDEN; import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.enunciate.Facet; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; import org.pentaho.platform.api.repository2.unified.UnifiedRepositoryException; import org.pentaho.platform.api.scheduler2.IJobTrigger; import org.pentaho.platform.api.scheduler2.Job; import org.pentaho.platform.api.scheduler2.Job.JobState; import org.pentaho.platform.api.scheduler2.SchedulerException; import org.pentaho.platform.repository2.unified.webservices.RepositoryFileDto; import org.pentaho.platform.web.http.api.resources.proxies.BlockStatusProxy; import org.pentaho.platform.web.http.api.resources.services.SchedulerService; import org.pentaho.platform.web.http.messages.Messages; /** * The SchedulerResource service provides the means to create, read, update, delete, and list schedules and blockout periods. Also provides the ability to control the status of schedules and the scheduler. */ @Path ( "/scheduler" ) public class SchedulerResource extends AbstractJaxRSResource { protected SchedulerService schedulerService; protected static final Log logger = LogFactory.getLog( SchedulerResource.class ); public SchedulerResource() { schedulerService = new SchedulerService(); } /** * Creates a new scheduled job. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/job * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobScheduleRequest> * <jobName>JobName</jobName> * <simpleJobTrigger> * <uiPassParam>MINUTES</uiPassParam> * <repeatInterval>1800</repeatInterval> * <repeatCount>-1</repeatCount> * <startTime>2014-08-14T11:46:00.000-04:00</startTime> * <endTime /> * </simpleJobTrigger> * <inputFile>/public/Steel Wheels/Top Customers (report).prpt</inputFile> * <outputFile>/public/output</outputFile> * <jobParameters> * <name>ParameterName</name> * <type>string</type> * <stringValue>false</stringValue> * </jobParameters> * </jobScheduleRequest> * </pre> * </p> * * @param scheduleRequest A JobScheduleRequest object to define the parameters of the job being created. * * @return A jax-rs Response object with the created jobId. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * admin JobName 1410786491777 * </pre> */ @POST @Path ( "/job" ) @Consumes ( { APPLICATION_JSON, APPLICATION_XML } ) @Produces ( "text/plain" ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Schedule created successfully." ), @ResponseCode ( code = 401, condition = "User is not allowed to create schedules." ), @ResponseCode ( code = 403, condition = "Cannot create schedules for the specified file." ), @ResponseCode ( code = 500, condition = "An error occurred while creating a schedule." ) } ) public Response createJob( JobScheduleRequest scheduleRequest ) { try { Job job = schedulerService.createJob( scheduleRequest ); return buildPlainTextOkResponse( job.getJobId() ); } catch ( SchedulerException e ) { return buildServerErrorResponse( e.getCause().getMessage() ); } catch ( IOException e ) { return buildServerErrorResponse( e.getCause().getMessage() ); } catch ( SecurityException e ) { return buildStatusResponse( UNAUTHORIZED ); } catch ( IllegalAccessException e ) { return buildStatusResponse( FORBIDDEN ); } } /** * Changes an existing job by creating an instance with new content (picked from {@code scheduleRequest}) and * removing the current instance. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/job/edit * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobScheduleRequest> * <jobName>JobName</jobName> * <simpleJobTrigger> * <uiPassParam>MINUTES</uiPassParam> * <repeatInterval>1800</repeatInterval> * <repeatCount>-1</repeatCount> * <startTime>2014-08-14T11:46:00.000-04:00</startTime> * <endTime /> * </simpleJobTrigger> * <inputFile>/public/Steel Wheels/Top Customers (report).prpt</inputFile> * <outputFile>/public/output</outputFile> * <jobParameters> * <name>ParameterName</name> * <type>string</type> * <stringValue>false</stringValue> * </jobParameters> * </jobScheduleRequest> * </jobId> * </pre> * </p> * * @param scheduleRequest A JobScheduleRequest object to define the parameters of the job being updated. * @return A jax-rs Response object with the created jobId. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * admin JobName 1410786491777 * </pre> */ @POST @Path ( "/job/update" ) @Consumes ( { APPLICATION_JSON, APPLICATION_XML } ) @Produces ( "text/plain" ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Schedule updated successfully." ), @ResponseCode ( code = 401, condition = "User is not allowed to update schedules." ), @ResponseCode ( code = 403, condition = "Cannot update schedules for the specified file." ), @ResponseCode ( code = 500, condition = "An error occurred while updating a schedule." ) } ) public Response updateJob( JobScheduleRequest scheduleRequest ) { try { Job job = schedulerService.updateJob( scheduleRequest ); return buildPlainTextOkResponse( job.getJobId() ); } catch ( SchedulerException e ) { return buildServerErrorResponse( e.getCause().getMessage() ); } catch ( IOException e ) { return buildServerErrorResponse( e.getCause().getMessage() ); } catch ( SecurityException e ) { return buildStatusResponse( UNAUTHORIZED ); } catch ( IllegalAccessException e ) { return buildStatusResponse( FORBIDDEN ); } } /** * Execute a previously scheduled job. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/triggerNow * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobRequest> * <jobId>admin JobName 1410786491777</jobId> * </jobRequest> * </pre> * </p> * * @param jobRequest A JobRequest object containing the jobId. * * @return A Response object indicating the status of the scheduler. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * NORMAL * </pre> */ @POST @Path ( "/triggerNow" ) @Produces ( "text/plain" ) @Consumes ( { APPLICATION_XML, APPLICATION_JSON } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Job triggered successfully." ), @ResponseCode ( code = 400, condition = "Invalid input." ), @ResponseCode ( code = 500, condition = "Invalid jobId." ) } ) public Response triggerNow( JobRequest jobRequest ) { try { Job job = schedulerService.triggerNow( jobRequest.getJobId() ); return buildPlainTextOkResponse( job.getState().name() ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Get the scheduled job created by the system for deleting generated files. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/getContentCleanerJob * </p> * * @return A Job object containing the definition of the content cleaner job. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * <job> * <groupName>admin</groupName> * <jobId>admin GeneratedContentCleaner 1408377444383</jobId> * <jobName>GeneratedContentCleaner</jobName> * <jobParams> * <jobParams> * <name>uiPassParam</name> * <value>DAILY</value> * </jobParams> * <jobParams> * <name>age</name> * <value>15552000</value> * </jobParams> * <jobParams> * <name>user_locale</name> * <value>en_US</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionUser</name> * <value>admin</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionClass</name> * <value>org.pentaho.platform.admin.GeneratedContentCleaner</value> * </jobParams> * <jobParams> * <name>lineage-id</name> * <value>c3cfbad4-2e34-4dbd-8071-a2f3c7e8fab9</value> * </jobParams> * </jobParams> * <jobTrigger xsi:type="simpleJobTrigger"> * <duration>-1</duration> * <startTime>2014-08-18T11:57:00-04:00</startTime> * <uiPassParam>DAILY</uiPassParam> * <repeatCount>-1</repeatCount> * <repeatInterval>86400</repeatInterval> * </jobTrigger> * <lastRun>2014-08-18T11:57:00-04:00</lastRun> * <nextRun>2014-08-19T11:57:00-04:00</nextRun> * <state>NORMAL</state> * <userName>admin</userName> * </job> * </pre> */ @GET @Path ( "/getContentCleanerJob" ) @Produces ( { APPLICATION_JSON, APPLICATION_XML } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Content cleaner job successfully retrieved." ), @ResponseCode ( code = 204, condition = "No content cleaner job exists." ), } ) public Job getContentCleanerJob() { try { return schedulerService.getContentCleanerJob(); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Retrieve the all the job(s) visible to the current users. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/jobs * </p> * * @param asCronString Cron string (Unused). * @return A list of jobs that are visible to the current users. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * <jobs> * <job> * <groupName>admin</groupName> * <jobId>admin PentahoSystemVersionCheck 1408369303507</jobId> * <jobName>PentahoSystemVersionCheck</jobName> * <jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionUser</name> * <value>admin</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionClass</name> * <value>org.pentaho.platform.scheduler2.versionchecker.VersionCheckerAction</value> * </jobParams> * <jobParams> * <name>lineage-id</name> * <value>1986cc90-cf87-43f6-8924-9d6e443e7d5d</value> * </jobParams> * <jobParams> * <name>versionRequestFlags</name> * <value>0</value> * </jobParams> * </jobParams> * <jobTrigger xsi:type="simpleJobTrigger"> * <duration>-1</duration> * <startTime>2014-08-18T09:41:43.506-04:00</startTime> * <repeatCount>-1</repeatCount> * <repeatInterval>86400</repeatInterval> * </jobTrigger> * <lastRun>2014-08-18T11:37:31.412-04:00</lastRun> * <nextRun>2014-08-19T09:41:43.506-04:00</nextRun> * <state>NORMAL</state> * <userName>admin</userName> * </job> * <job> * <groupName>admin</groupName> * <jobId>admin UpdateAuditData 1408373019115</jobId> * <jobName>UpdateAuditData</jobName> * <jobParams> * <jobParams> * <name>autoCreateUniqueFilename</name> * <value>false</value> * </jobParams> * <jobParams> * <name>uiPassParam</name> * <value>MINUTES</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-StreamProvider</name> * <value>input file = /public/pentaho-operations-mart/update_audit_mart_data/UpdateAuditData.xaction:outputFile = /public/pentaho-operations-mart/generated_logs/UpdateAuditData.*</value> * </jobParams> * <jobParams> * <name>user_locale</name> * <value>en_US</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionUser</name> * <value>admin</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionId</name> * <value>xaction.backgroundExecution</value> * </jobParams> * <jobParams> * <name>lineage-id</name> * <value>1f2402c4-0a70-40e4-b428-0d328f504cb3</value> * </jobParams> * </jobParams> * <jobTrigger xsi:type="simpleJobTrigger"> * <duration>-1</duration> * <startTime>2014-07-14T12:47:00-04:00</startTime> * <uiPassParam>MINUTES</uiPassParam> * <repeatCount>-1</repeatCount> * <repeatInterval>1800</repeatInterval> * </jobTrigger> * <lastRun>2014-08-18T12:47:00-04:00</lastRun> * <nextRun>2014-08-18T13:17:00-04:00</nextRun> * <state>NORMAL</state> * <userName>admin</userName> * </job> * </jobs> * </pre> */ @Deprecated @GET @Path ( "/jobs" ) @Produces ( { APPLICATION_JSON, APPLICATION_XML } ) @Facet ( name = "Unsupported" ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Jobs retrieved successfully." ), @ResponseCode ( code = 500, condition = "Error while retrieving jobs." ) } ) public List<Job> getJobs( @DefaultValue ( "false" ) @QueryParam ( "asCronString" ) Boolean asCronString ) { try { return schedulerService.getJobs(); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Retrieve the all the scheduled job(s) visible to the current users. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/getJobs * </p> * * @return A list of jobs that are visible to the current users. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * <jobs> * <job> * <groupName>admin</groupName> * <jobId>admin PentahoSystemVersionCheck 1408369303507</jobId> * <jobName>PentahoSystemVersionCheck</jobName> * <jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionUser</name> * <value>admin</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionClass</name> * <value>org.pentaho.platform.scheduler2.versionchecker.VersionCheckerAction</value> * </jobParams> * <jobParams> * <name>lineage-id</name> * <value>1986cc90-cf87-43f6-8924-9d6e443e7d5d</value> * </jobParams> * <jobParams> * <name>versionRequestFlags</name> * <value>0</value> * </jobParams> * </jobParams> * <jobTrigger xsi:type="simpleJobTrigger"> * <duration>-1</duration> * <startTime>2014-08-18T09:41:43.506-04:00</startTime> * <repeatCount>-1</repeatCount> * <repeatInterval>86400</repeatInterval> * </jobTrigger> * <lastRun>2014-08-18T11:37:31.412-04:00</lastRun> * <nextRun>2014-08-19T09:41:43.506-04:00</nextRun> * <state>NORMAL</state> * <userName>admin</userName> * </job> * <job> * <groupName>admin</groupName> * <jobId>admin UpdateAuditData 1408373019115</jobId> * <jobName>UpdateAuditData</jobName> * <jobParams> * <jobParams> * <name>autoCreateUniqueFilename</name> * <value>false</value> * </jobParams> * <jobParams> * <name>uiPassParam</name> * <value>MINUTES</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-StreamProvider</name> * <value>input file = /public/pentaho-operations-mart/update_audit_mart_data/UpdateAuditData.xaction:outputFile = /public/pentaho-operations-mart/generated_logs/UpdateAuditData.*</value> * </jobParams> * <jobParams> * <name>user_locale</name> * <value>en_US</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionUser</name> * <value>admin</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionId</name> * <value>xaction.backgroundExecution</value> * </jobParams> * <jobParams> * <name>lineage-id</name> * <value>1f2402c4-0a70-40e4-b428-0d328f504cb3</value> * </jobParams> * </jobParams> * <jobTrigger xsi:type="simpleJobTrigger"> * <duration>-1</duration> * <startTime>2014-07-14T12:47:00-04:00</startTime> * <uiPassParam>MINUTES</uiPassParam> * <repeatCount>-1</repeatCount> * <repeatInterval>1800</repeatInterval> * </jobTrigger> * <lastRun>2014-08-18T12:47:00-04:00</lastRun> * <nextRun>2014-08-18T13:17:00-04:00</nextRun> * <state>NORMAL</state> * <userName>admin</userName> * </job> * </jobs> * </pre> */ @GET @Path ( "/getJobs" ) @Produces ( { APPLICATION_JSON, APPLICATION_XML } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Jobs retrieved successfully." ), @ResponseCode ( code = 500, condition = "Error while retrieving jobs." ), } ) public List<Job> getAllJobs() { try { return schedulerService.getJobs(); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Checks whether the current user may schedule a repository file in the platform. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/isScheduleAllowed?id=b5f806b9-9f72-4814-b1e0-aa9e0ece7e1a * </p> * * @param id The repository file ID of the content to checked. * * @return true or false. true indicates scheduling is allowed and false indicates scheduling is not allowed for the file. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * true * </pre> */ @GET @Path ( "/isScheduleAllowed" ) @Produces ( TEXT_PLAIN ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully retrieved scheduling ability of repository file." ), @ResponseCode ( code = 500, condition = "Invalid repository file id." ), } ) public String isScheduleAllowed( @QueryParam ( "id" ) String id ) { return "" + schedulerService.isScheduleAllowed( id ); } /** * Checks whether the current user has authority to schedule any content in the platform. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/canSchedule * </p> * * @return true or false. true indicates scheduling is allowed and false indicates scheduling is not allowed for the user. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * true * </pre> */ @GET @Path ( "/canSchedule" ) @Produces ( TEXT_PLAIN ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successful retrieved the scheduling permission." ), @ResponseCode ( code = 500, condition = "Unable to retrieve the scheduling permission." ) } ) public String doGetCanSchedule() { return schedulerService.doGetCanSchedule(); } /** * Returns the state of the scheduler with the value of RUNNING or PAUSED. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/state * </p> * * @return status of the scheduler as RUNNING or PAUSED. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * RUNNING * </pre> */ @GET @Path ( "/state" ) @Produces ( "text/plain" ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully retrieved the state of the scheduler." ), @ResponseCode ( code = 500, condition = "An error occurred when getting the state of the scheduler." ) } ) public Response getState() { try { String state = schedulerService.getState(); return buildPlainTextOkResponse( state ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Resume the scheduler from a paused state. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/start * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * This POST body does not contain data. * </pre> * </p> * * @return A jax-rs Response object containing the status of the scheduler. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * RUNNING * </pre> */ @POST @Path ( "/start" ) @Produces ( "text/plain" ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully started the server." ), @ResponseCode ( code = 500, condition = "An error occurred when resuming the scheduler." ) } ) public Response start() { try { String status = schedulerService.start(); return buildPlainTextOkResponse( status ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Pause the scheduler from a running state. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/pause * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * This POST body does not contain data. * </pre> * </p> * * @return A jax-rs Response object containing the status of the scheduler. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * PAUSED * </pre> */ @POST @Path ( "/pause" ) @Produces ( "text/plain" ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully paused the server." ), @ResponseCode ( code = 500, condition = "An error occurred when pausing the scheduler." ) } ) public Response pause() { try { String status = schedulerService.pause(); return buildPlainTextOkResponse( status ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Shuts down the scheduler. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/shutdown * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * This POST body does not contain data. * </pre> * </p> * * @return A jax-rs Response object containing the status of the scheduler. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * PAUSED * </pre> */ @POST @Path ( "/shutdown" ) @Produces ( "text/plain" ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully shut down the server." ), @ResponseCode ( code = 500, condition = "An error occurred when shutting down the scheduler." ) } ) public Response shutdown() { try { String status = schedulerService.shutdown(); return buildPlainTextOkResponse( status ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Checks the state of the selected scheduled job. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/jobState * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobRequest> * <jobId>admin JobName 1410786491777</jobId> * </jobRequest> * </pre> * </p> * * @param jobRequest A JobRequest object containing the jobId. * * @return A jax-rs Response object containing the status of the scheduled job. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * NORMAL * </pre> */ @POST @Path ( "/jobState" ) @Produces ( "text/plain" ) @Consumes ( { APPLICATION_XML, APPLICATION_JSON } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully retrieved the state of the requested job." ), @ResponseCode ( code = 500, condition = "Invalid jobId." ) } ) public Response getJobState( JobRequest jobRequest ) { try { return buildPlainTextOkResponse( schedulerService.getJobState( jobRequest ).name() ); } catch ( UnsupportedOperationException e ) { return buildPlainTextStatusResponse( UNAUTHORIZED ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Pause the specified scheduled job. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/pauseJob * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobRequest> * <jobId>admin JobName 1410786491777</jobId> * </jobRequest> * </pre> * </p> * * @param jobRequest A JobRequest object containing the jobId. * * @return A jax-rs Response object containing the status of the scheduled job. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * PAUSED * </pre> */ @POST @Path ( "/pauseJob" ) @Produces ( "text/plain" ) @Consumes ( { APPLICATION_XML, APPLICATION_JSON } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully paused the job." ), @ResponseCode ( code = 500, condition = "Invalid jobId." ) } ) public Response pauseJob( JobRequest jobRequest ) { try { JobState state = schedulerService.pauseJob( jobRequest.getJobId() ); return buildPlainTextOkResponse( state.name() ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Resume the specified scheduled job. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/resumeJob * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobRequest> * <jobId>admin JobName 1410786491777</jobId> * </jobRequest> * </pre> * </p> * * @param jobRequest A JobRequest object containing the jobId. * * @return A jax-rs Response object containing the status of the scheduled job. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * NORMAL * </pre> */ @POST @Path ( "/resumeJob" ) @Produces ( "text/plain" ) @Consumes ( { APPLICATION_XML, APPLICATION_JSON } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully resumed the job." ), @ResponseCode ( code = 500, condition = "Invalid jobId." ) } ) public Response resumeJob( JobRequest jobRequest ) { try { JobState state = schedulerService.resumeJob( jobRequest.getJobId() ); return buildPlainTextOkResponse( state.name() ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Delete the specified scheduled job from the platform. * * <p><b>Example Request:</b><br /> * DELETE pentaho/api/scheduler/removeJob * </p> * <br /><b>DELETE data:</b> * <pre function="syntax.xml"> * <jobRequest> * <jobId>admin BlockoutAction 1410786491503</jobId> * </jobRequest> * </pre> * </p> * * @param jobRequest A JobRequest object containing the jobId. * * @return A jax-rs Response object containing the status of the scheduled job. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * REMOVED * </pre> */ @DELETE @Path ( "/removeJob" ) @Produces ( "text/plain" ) @Consumes ( { APPLICATION_XML, APPLICATION_JSON } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully removed the job." ), @ResponseCode ( code = 500, condition = "Invalid jobId." ) } ) public Response removeJob( JobRequest jobRequest ) { try { if ( schedulerService.removeJob( jobRequest.getJobId() ) ) { return buildPlainTextOkResponse( "REMOVED" ); } Job job = schedulerService.getJob( jobRequest.getJobId() ); return buildPlainTextOkResponse( job.getState().name() ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } /** * Return the information for a specified job. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/jobinfo?jobId=admin%09JobName%091410786491777 * </p> * * @param jobId The jobId of the job for which we are requesting information. * @param asCronString Cron string (Unused) * * @return A Job object containing the info for the specified job. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * <?xml version="1.0" encoding="UTF-8" standalone="yes"?><job><jobId>admin JobName 1410786491777</jobId><jobName>JobName</jobName><jobParams><jobParams><name>uiPassParam</name><value>MINUTES</value></jobParams><jobParams><name>ActionAdapterQuartzJob-StreamProvider</name><value>input file = /public/Steel Wheels/Top Customers (report).prpt:outputFile = /home/admin/JobName.*</value></jobParams><jobParams><name>user_locale</name><value>en_US</value></jobParams><jobParams><name>ActionAdapterQuartzJob-ActionUser</name><value>admin</value></jobParams><jobParams><name>ActionAdapterQuartzJob-ActionId</name><value>prpt.backgroundExecution</value></jobParams><jobParams><name>ParameterName</name><value>false</value></jobParams><jobParams><name>lineage-id</name><value>5212a120-3294-49e8-9c5d-c755b9766c43</value></jobParams></jobParams><jobTrigger xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="simpleJobTrigger"><duration>-1</duration><startTime>2014-08-14T11:46:00-04:00</startTime><uiPassParam>MINUTES</uiPassParam><repeatCount>-1</repeatCount><repeatInterval>1800</repeatInterval></jobTrigger><nextRun>2014-08-14T11:46:00-04:00</nextRun><state>NORMAL</state><userName>admin</userName></job> * </pre> */ @GET @Path ( "/jobinfo" ) @Produces ( { APPLICATION_JSON, APPLICATION_XML } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully retrieved the information for the requested job." ), @ResponseCode ( code = 500, condition = "Invalid jobId." ) } ) public Job getJob( @QueryParam( "jobId" ) String jobId, @DefaultValue( "false" ) @QueryParam( "asCronString" ) String asCronString ) { try { return schedulerService.getJobInfo( jobId ); } catch ( SchedulerException e ) { throw new RuntimeException( e ); } } @Deprecated @GET @Path ( "/jobinfotest" ) @Produces ( { APPLICATION_JSON } ) @Facet ( name = "Unsupported" ) public JobScheduleRequest getJobInfo() { return schedulerService.getJobInfo(); } /** * @return list of Job * @deprecated Method is deprecated as the name getBlockoutJobs is preferred over getJobs * * Retrieves all blockout jobs in the system */ @Deprecated @Facet ( name = "Unsupported" ) public List<Job> getJobs() { return getBlockoutJobs(); } /** * Get all the blockout jobs in the system. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/blockout/blockoutjobs * </p> * * @return A Response object that contains a list of blockout jobs. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * <jobs> * <job> * <groupName>admin</groupName> * <jobId>admin BlockoutAction 1408457558636</jobId> * <jobName>BlockoutAction</jobName> * <jobParams> * <jobParams> * <name>TIME_ZONE_PARAM</name> * <value>America/New_York</value> * </jobParams> * <jobParams> * <name>DURATION_PARAM</name> * <value>10080000</value> * </jobParams> * <jobParams> * <name>uiPassParam</name> * <value>DAILY</value> * </jobParams> * <jobParams> * <name>user_locale</name> * <value>en_US</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionUser</name> * <value>admin</value> * </jobParams> * <jobParams> * <name>ActionAdapterQuartzJob-ActionClass</name> * <value>org.pentaho.platform.scheduler2.blockout.BlockoutAction</value> * </jobParams> * <jobParams> * <name>lineage-id</name> * <value>0989726c-3247-4864-bc79-8e2a1dc60c58</value> * </jobParams> * </jobParams> * <jobTrigger xsi:type="complexJobTrigger"> * <cronString>0 12 10 ? * 2,3,4,5,6 *</cronString> * <duration>10080000</duration> * <startTime>2014-08-19T10:12:00-04:00</startTime> * <uiPassParam>DAILY</uiPassParam> * <dayOfMonthRecurrences /> * <dayOfWeekRecurrences> * <recurrenceList> * <values>2</values> * <values>3</values> * <values>4</values> * <values>5</values> * <values>6</values> * </recurrenceList> * </dayOfWeekRecurrences> * <hourlyRecurrences> * <recurrenceList> * <values>10</values> * </recurrenceList> * </hourlyRecurrences> * <minuteRecurrences> * <recurrenceList> * <values>12</values> * </recurrenceList> * </minuteRecurrences> * <monthlyRecurrences /> * <secondRecurrences> * <recurrenceList> * <values>0</values> * </recurrenceList> * </secondRecurrences> * <yearlyRecurrences /> * </jobTrigger> * <nextRun>2014-08-20T10:12:00-04:00</nextRun> * <state>NORMAL</state> * <userName>admin</userName> * </job> * </jobs> * </pre> */ @GET @Path ( "/blockout/blockoutjobs" ) @Produces ( { APPLICATION_JSON, APPLICATION_XML } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully retrieved blockout jobs." ), } ) public List<Job> getBlockoutJobs() { return schedulerService.getBlockOutJobs(); } /** * Checks if there are blockouts in the system. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/blockout/hasblockouts * </p> * * @return true or false whether there are blackouts or not. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * true * </pre> */ @GET @Path ( "/blockout/hasblockouts" ) @Produces ( { TEXT_PLAIN } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully determined whether or not the system contains blockouts." ), } ) public Response hasBlockouts() { Boolean hasBlockouts = schedulerService.hasBlockouts(); return buildOkResponse( hasBlockouts.toString() ); } /** * Creates a new blockout for scheduled jobs. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/blockout/add * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobScheduleRequest> * <jobName>DAILY-1820438815:admin:7740000</jobName> * <complexJobTrigger> * <uiPassParam>DAILY</uiPassParam> * <daysOfWeek>1</daysOfWeek> * <daysOfWeek>2</daysOfWeek> * <daysOfWeek>3</daysOfWeek> * <daysOfWeek>4</daysOfWeek> * <daysOfWeek>5</daysOfWeek> * <startTime>2014-08-19T10:51:00.000-04:00</startTime> * <endTime /> * </complexJobTrigger> * <inputFile></inputFile> * <outputFile></outputFile> * <duration>7740000</duration> * <timeZone>America/New_York</timeZone> * </jobScheduleRequest> * </pre> * </p> * * @param jobScheduleRequest A JobScheduleRequest object defining the blockout job. * * @return A Response object which contains the ID of the blockout which was created. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * admin BlockoutAction 1410786491209 * </pre> */ @POST @Path ( "/blockout/add" ) @Consumes ( { APPLICATION_JSON, APPLICATION_XML } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successful operation." ), @ResponseCode ( code = 401, condition = "User is not authorized to create blockout." ) } ) public Response addBlockout( JobScheduleRequest jobScheduleRequest ) { try { Job job = schedulerService.addBlockout( jobScheduleRequest ); return buildPlainTextOkResponse( job.getJobId() ); } catch ( IOException e ) { return buildStatusResponse( UNAUTHORIZED ); } catch ( SchedulerException e ) { return buildStatusResponse( UNAUTHORIZED ); } catch ( IllegalAccessException e ) { return buildStatusResponse( UNAUTHORIZED ); } } /** * Update an existing blockout. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/blockout/update?jobid=admin%09BlockoutAction%091410786491209 * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobScheduleRequest> * <jobName>DAILY-1820438815:admin:7740000</jobName> * <complexJobTrigger> * <uiPassParam>DAILY</uiPassParam> * <daysOfWeek>1</daysOfWeek> * <daysOfWeek>2</daysOfWeek> * <daysOfWeek>3</daysOfWeek> * <daysOfWeek>4</daysOfWeek> * <daysOfWeek>5</daysOfWeek> * <startTime>2012-01-12T10:51:00.000-04:00</startTime> * <endTime /> * </complexJobTrigger> * <inputFile></inputFile> * <outputFile></outputFile> * <duration>7740000</duration> * <timeZone>America/New_York</timeZone> * </jobScheduleRequest> * </pre> * </p> * * @param jobId The jobId of the blockout we are editing. * @param jobScheduleRequest The payload containing the definition of the blockout. * * @return A Response object which contains the ID of the blockout which was created. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * admin BlockoutAction 1410786491503 * </pre> */ @POST @Path ( "/blockout/update" ) @Consumes ( { APPLICATION_JSON, APPLICATION_XML } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successful operation." ), @ResponseCode ( code = 401, condition = "User is not authorized to update blockout." ) } ) public Response updateBlockout( @QueryParam ( "jobid" ) String jobId, JobScheduleRequest jobScheduleRequest ) { try { Job job = schedulerService.updateBlockout( jobId, jobScheduleRequest ); return buildPlainTextOkResponse( job.getJobId() ); } catch ( IOException e ) { return buildStatusResponse( Status.UNAUTHORIZED ); } catch ( SchedulerException e ) { return buildStatusResponse( Status.UNAUTHORIZED ); } catch ( IllegalAccessException e ) { return buildStatusResponse( Status.UNAUTHORIZED ); } } /** * Checks if the selected blockout schedule will be fired. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/blockout/willFire * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobScheduleRequest> * <jobName>DAILY-1820438815:admin:7740000</jobName> * <complexJobTrigger> * <uiPassParam>DAILY</uiPassParam> * <daysOfWeek>1</daysOfWeek> * <daysOfWeek>2</daysOfWeek> * <daysOfWeek>3</daysOfWeek> * <daysOfWeek>4</daysOfWeek> * <daysOfWeek>5</daysOfWeek> * <startTime>2014-08-19T10:51:00.000-04:00</startTime> * <endTime /> * </complexJobTrigger> * <inputFile></inputFile> * <outputFile></outputFile> * <duration>7740000</duration> * <timeZone>America/New_York</timeZone> * </jobScheduleRequest> * </pre> * </p> * * @param jobScheduleRequest The payload containing the definition of the blockout. * * @return true or false indicating whether or not the blockout will fire. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * false * </pre> */ @POST @Path ( "/blockout/willFire" ) @Consumes ( { APPLICATION_JSON, APPLICATION_XML } ) @Produces ( { TEXT_PLAIN } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successful operation." ), @ResponseCode ( code = 500, condition = "An error occurred while determining blockouts being fired." ) } ) public Response blockoutWillFire( JobScheduleRequest jobScheduleRequest ) { Boolean willFire; try { willFire = schedulerService.willFire( convertScheduleRequestToJobTrigger( jobScheduleRequest ) ); } catch ( UnifiedRepositoryException e ) { return buildServerErrorResponse( e ); } catch ( SchedulerException e ) { return buildServerErrorResponse( e ); } return buildOkResponse( willFire.toString() ); } /** * Checks if the selected blockout schedule should be fired now. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/blockout/shouldFireNow * </p> * * @return true or false whether or not the blockout should fire now. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * true * </pre> */ @GET @Path ( "/blockout/shouldFireNow" ) @Produces ( { TEXT_PLAIN } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successful operation." ) } ) public Response shouldFireNow() { Boolean result = schedulerService.shouldFireNow(); return buildOkResponse( result.toString() ); } /** * Check the status of the selected blockout schedule. * * <p><b>Example Request:</b><br /> * POST pentaho/api/scheduler/blockout/blockstatus * </p> * <br /><b>POST data:</b> * <pre function="syntax.xml"> * <jobScheduleRequest> * <jobName>DAILY-1820438815:admin:7740000</jobName> * <complexJobTrigger> * <uiPassParam>DAILY</uiPassParam> * <daysOfWeek>1</daysOfWeek> * <daysOfWeek>2</daysOfWeek> * <daysOfWeek>3</daysOfWeek> * <daysOfWeek>4</daysOfWeek> * <daysOfWeek>5</daysOfWeek> * <startTime>2014-08-19T10:51:00.000-04:00</startTime> * <endTime /> * </complexJobTrigger> * <inputFile></inputFile> * <outputFile></outputFile> * <duration>7740000</duration> * <timeZone>America/New_York</timeZone> * </jobScheduleRequest> * </pre> * </p> * * @param jobScheduleRequest The payload containing the definition of the blockout. * * @return A Response object which contains a BlockStatusProxy which contains totallyBlocked and partiallyBlocked flags. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * <blockStatusProxy> * <partiallyBlocked>true</partiallyBlocked> * <totallyBlocked>true</totallyBlocked> * </blockStatusProxy> * </pre> */ @POST @Path ( "/blockout/blockstatus" ) @Consumes ( { APPLICATION_JSON, APPLICATION_XML } ) @Produces ( { APPLICATION_JSON, APPLICATION_XML } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully got the blockout status." ), @ResponseCode ( code = 401, condition = "User is not authorized to get the blockout status." ) } ) public Response getBlockStatus( JobScheduleRequest jobScheduleRequest ) { try { BlockStatusProxy blockStatusProxy = schedulerService.getBlockStatus( jobScheduleRequest ); return buildOkResponse( blockStatusProxy ); } catch ( SchedulerException e ) { return buildStatusResponse( Status.UNAUTHORIZED ); } } /** * Retrieve the list of execute content by lineage id. * * <p><b>Example Request:</b><br /> * GET pentaho/api/scheduler/generatedContentForSchedule?lineageId=:public:Steel%20Wheels:Inventory%20List%20(report).prpt * </p> * * @param lineageId the path for the file. * * @return A list of RepositoryFileDto objects. * * <p><b>Example Response:</b></p> * <pre function="syntax.xml"> * <List> * <repositoryFileDto> * <createdDate>1402911997019</createdDate> * <fileSize>3461</fileSize> * <folder>false</folder> * <hidden>false</hidden> * <id>ff11ac89-7eda-4c03-aab1-e27f9048fd38</id> * <lastModifiedDate>1406647160536</lastModifiedDate> * <locale>en</locale> * <localePropertiesMapEntries> * <localeMapDto> * <locale>default</locale> * <properties> * <stringKeyStringValueDto> * <key>file.title</key> * <value>myFile</value> * </stringKeyStringValueDto> * <stringKeyStringValueDto> * <key>jcr:primaryType</key> * <value>nt:unstructured</value> * </stringKeyStringValueDto> * <stringKeyStringValueDto> * <key>title</key> * <value>myFile</value> * </stringKeyStringValueDto> * <stringKeyStringValueDto> * <key>file.description</key> * <value>myFile Description</value> * </stringKeyStringValueDto> * </properties> * </localeMapDto> * </localePropertiesMapEntries> * <locked>false</locked> * <name>myFile.prpt</name></name> * <originalParentFolderPath>/public/admin</originalParentFolderPath> * <ownerType>-1</ownerType> * <path>/public/admin/ff11ac89-7eda-4c03-aab1-e27f9048fd38</path> * <title>myFile</title> * <versionId>1.9</versionId> * <versioned>true</versioned> * </repositoryFileAclDto> * </List> * </pre> */ @GET @Path ( "/generatedContentForSchedule" ) @Produces ( { APPLICATION_XML, APPLICATION_JSON } ) @StatusCodes ( { @ResponseCode ( code = 200, condition = "Successfully got the generated content for schedule" ) } ) public List<RepositoryFileDto> doGetGeneratedContentForSchedule( @QueryParam ( "lineageId" ) String lineageId ) { List<RepositoryFileDto> repositoryFileDtoList = new ArrayList<RepositoryFileDto>(); try { repositoryFileDtoList = schedulerService.doGetGeneratedContentForSchedule( lineageId ); } catch ( FileNotFoundException e ) { //return the empty list } catch ( Throwable t ) { logger .error( Messages.getInstance().getString( "FileResource.GENERATED_CONTENT_FOR_USER_FAILED", lineageId ), t ); } return repositoryFileDtoList; } protected Response buildOkResponse( Object entity ) { return Response.ok( entity ).build(); } protected Response buildPlainTextOkResponse( String msg ) { return Response.ok( msg ).type( MediaType.TEXT_PLAIN ).build(); } protected Response buildServerErrorResponse( Object entity ) { return Response.serverError().entity( entity ).build(); } protected Response buildStatusResponse( Status status ) { return Response.status( status ).build(); } protected Response buildPlainTextStatusResponse( Status status ) { return Response.status( status ).type( MediaType.TEXT_PLAIN ).build(); } protected JobRequest getJobRequest() { return new JobRequest(); } protected IJobTrigger convertScheduleRequestToJobTrigger( JobScheduleRequest request ) throws SchedulerException { return SchedulerResourceUtil.convertScheduleRequestToJobTrigger( request, schedulerService.getScheduler() ); } }