/*!
* 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 );
}
}
/**
* 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() );
}
}