/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package org.pentaho.di.www.jaxrs;
import java.util.UUID;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.logging.KettleLogStore;
import org.pentaho.di.core.logging.LoggingObjectType;
import org.pentaho.di.core.logging.SimpleLoggingObject;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.job.Job;
import org.pentaho.di.job.JobAdapter;
import org.pentaho.di.job.JobConfiguration;
import org.pentaho.di.job.JobExecutionConfiguration;
import org.pentaho.di.job.JobMeta;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.www.CarteObjectEntry;
import org.pentaho.di.www.CarteSingleton;
@Path( "/carte/job" )
public class JobResource {
public JobResource() {
}
@GET
@Path( "/log/{id : .+}" )
@Produces( { MediaType.TEXT_PLAIN } )
public String getJobLog( @PathParam( "id" ) String id ) {
return getJobLog( id, 0 );
}
@GET
@Path( "/log/{id : .+}/{logStart : .+}" )
@Produces( { MediaType.TEXT_PLAIN } )
public String getJobLog( @PathParam( "id" ) String id, @PathParam( "logStart" ) int startLineNr ) {
int lastLineNr = KettleLogStore.getLastBufferLineNr();
Job job = CarteResource.getJob( id );
String logText =
KettleLogStore.getAppender().getBuffer(
job.getLogChannel().getLogChannelId(), false, startLineNr, lastLineNr ).toString();
return logText;
}
@GET
@Path( "/status/{id : .+}" )
@Produces( { MediaType.APPLICATION_JSON } )
public JobStatus getJobStatus( @PathParam( "id" ) String id ) {
JobStatus status = new JobStatus();
// find job
Job job = CarteResource.getJob( id );
CarteObjectEntry entry = CarteResource.getCarteObjectEntry( id );
status.setId( entry.getId() );
status.setName( entry.getName() );
status.setStatus( job.getStatus() );
return status;
}
// change from GET to UPDATE/POST for proper REST method
@GET
@Path( "/start/{id : .+}" )
@Produces( { MediaType.APPLICATION_JSON } )
public JobStatus startJob( @PathParam( "id" ) String id ) {
Job job = CarteResource.getJob( id );
CarteObjectEntry entry = CarteResource.getCarteObjectEntry( id );
try {
if ( job.isInitialized() && !job.isActive() ) {
// Re-create the job from the jobMeta
//
// We might need to re-connect to the repository
//
if ( job.getRep() != null && !job.getRep().isConnected() ) {
if ( job.getRep().getUserInfo() != null ) {
job.getRep().connect( job.getRep().getUserInfo().getLogin(), job.getRep().getUserInfo().getPassword() );
} else {
job.getRep().connect( null, null );
}
}
// Create a new job object to start from a sane state. Then replace
// the new job in the job map
//
synchronized ( this ) {
JobConfiguration jobConfiguration = CarteSingleton.getInstance().getJobMap().getConfiguration( entry );
String carteObjectId = UUID.randomUUID().toString();
SimpleLoggingObject servletLoggingObject =
new SimpleLoggingObject( getClass().getName(), LoggingObjectType.CARTE, null );
servletLoggingObject.setContainerObjectId( carteObjectId );
Job newJob = new Job( job.getRep(), job.getJobMeta(), servletLoggingObject );
newJob.setLogLevel( job.getLogLevel() );
// Discard old log lines from the old job
//
KettleLogStore.discardLines( job.getLogChannelId(), true );
CarteSingleton.getInstance().getJobMap().replaceJob( entry, newJob, jobConfiguration );
job = newJob;
}
}
job.start();
} catch ( KettleException e ) {
e.printStackTrace();
}
return getJobStatus( id );
}
@GET
@Path( "/stop/{id : .+}" )
@Produces( { MediaType.APPLICATION_JSON } )
public JobStatus stopJob( @PathParam( "id" ) String id ) {
Job job = CarteResource.getJob( id );
job.stopAll();
return getJobStatus( id );
}
@GET
@Path( "/remove/{id : .+}" )
public Response removeJob( @PathParam( "id" ) String id ) {
Job job = CarteResource.getJob( id );
CarteObjectEntry entry = CarteResource.getCarteObjectEntry( id );
KettleLogStore.discardLines( job.getLogChannelId(), true );
CarteSingleton.getInstance().getJobMap().removeJob( entry );
return Response.ok().build();
}
@PUT
@Path( "/add" )
@Produces( { MediaType.APPLICATION_JSON } )
public JobStatus addJob( String xml ) {
// Parse the XML, create a job configuration
//
// System.out.println(xml);
//
JobConfiguration jobConfiguration;
try {
jobConfiguration = JobConfiguration.fromXML( xml.toString() );
JobMeta jobMeta = jobConfiguration.getJobMeta();
JobExecutionConfiguration jobExecutionConfiguration = jobConfiguration.getJobExecutionConfiguration();
jobMeta.setLogLevel( jobExecutionConfiguration.getLogLevel() );
jobMeta.injectVariables( jobExecutionConfiguration.getVariables() );
// If there was a repository, we know about it at this point in time.
//
final Repository repository = jobConfiguration.getJobExecutionConfiguration().getRepository();
String carteObjectId = UUID.randomUUID().toString();
SimpleLoggingObject servletLoggingObject =
new SimpleLoggingObject( getClass().getName(), LoggingObjectType.CARTE, null );
servletLoggingObject.setContainerObjectId( carteObjectId );
servletLoggingObject.setLogLevel( jobExecutionConfiguration.getLogLevel() );
// Create the transformation and store in the list...
//
final Job job = new Job( repository, jobMeta, servletLoggingObject );
// Setting variables
//
job.initializeVariablesFrom( null );
job.getJobMeta().setInternalKettleVariables( job );
job.injectVariables( jobConfiguration.getJobExecutionConfiguration().getVariables() );
job.setArguments( jobExecutionConfiguration.getArgumentStrings() );
// Also copy the parameters over...
//
job.copyParametersFrom( jobMeta );
job.clearParameters();
String[] parameterNames = job.listParameters();
for ( int idx = 0; idx < parameterNames.length; idx++ ) {
// Grab the parameter value set in the job entry
//
String thisValue = jobExecutionConfiguration.getParams().get( parameterNames[idx] );
if ( !Utils.isEmpty( thisValue ) ) {
// Set the value as specified by the user in the job entry
//
jobMeta.setParameterValue( parameterNames[idx], thisValue );
}
}
jobMeta.activateParameters();
job.setSocketRepository( CarteSingleton.getInstance().getSocketRepository() );
CarteSingleton.getInstance().getJobMap().addJob( job.getJobname(), carteObjectId, job, jobConfiguration );
// Make sure to disconnect from the repository when the job finishes.
//
if ( repository != null ) {
job.addJobListener( new JobAdapter() {
public void jobFinished( Job job ) {
repository.disconnect();
}
} );
}
return getJobStatus( carteObjectId );
} catch ( KettleException e ) {
e.printStackTrace();
}
return null;
}
}