All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pentaho.di.www.GetTransStatusServlet Maven / Gradle / Ivy

The newest version!
/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2019 by Hitachi Vantara : 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;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.nio.charset.Charset;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.common.annotations.VisibleForTesting;
import org.owasp.encoder.Encode;
import org.pentaho.di.cluster.HttpUtil;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.EnvUtil;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.gui.Point;
import org.pentaho.di.core.logging.KettleLogStore;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.step.BaseStepData.StepExecutionStatus;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepStatus;
import org.pentaho.di.www.cache.CarteStatusCache;


public class GetTransStatusServlet extends BaseHttpServlet implements CartePluginInterface {

  private static Class PKG = GetTransStatusServlet.class; // for i18n purposes, needed by Translator2!!

  private static final long serialVersionUID = 3634806745372015720L;

  public static final String CONTEXT_PATH = "/kettle/transStatus";

  public static final String SEND_RESULT = "sendResult";

  private static final byte[] XML_HEADER =
    XMLHandler.getXMLHeader( Const.XML_ENCODING ).getBytes( Charset.forName( Const.XML_ENCODING ) );

  @VisibleForTesting
  CarteStatusCache cache = CarteStatusCache.getInstance();

  public GetTransStatusServlet() {
  }

  public GetTransStatusServlet( TransformationMap transformationMap ) {
    super( transformationMap );
  }

  /**
   

/kettle/transStatus

GET

Retrieves status of the specified transformation. Status is returned as HTML or XML output depending on the input parameters. Status contains information about last execution of the transformation.

Example Request:

   GET /kettle/transStatus/?name=dummy-trans&xml=Y
   

Parameters

name description type
name Name of the transformation to be used for status generation. query
xml Boolean flag which defines output format Y forces XML output to be generated. HTML is returned otherwise. boolean, optional
id Carte id of the transformation to be used for status generation. query, optional
from Start line number of the execution log to be included into response. integer, optional

Response Body

element: (custom)
media types: text/xml, text/html

Response XML or HTML response containing details about the transformation specified. If an error occurs during method invocation result field of the response will contain ERROR status.

Example Response:

   
   
   dummy-trans
   c56961b2-c848-49b8-abde-76c8015e29b0
   Stopped
   
   N
   
   Dummy (do nothing)
   00
   00
   00
   00
   Stopped0.0
   --Y
   N
   
   
   0
   37
   
   0
   0
   0
   0
   0
   0
   0
   0
   0
   0
   Y
   0
   Y
   10e2c832-07da-409a-a5ba-4b90a234e957
   
   
   
   
   <![CDATA[H4sIAAAAAAAAADMyMDTRNzTUNzJRMDSyMrC0MjFV0FVIKc3NrdQtKUrMKwbyXDKLCxJLkjMy89IViksSi0pSUxTS8osUwPJARm5iSWZ+nkI0kq5YXi4AQVH5bFoAAAA=]]>
   
   

Status Codes

code description
200 Request was processed.
500 Internal server error occurs during request processing.
*/ public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { if ( isJettyMode() && !request.getContextPath().startsWith( CONTEXT_PATH ) ) { return; } if ( log.isDebug() ) { logDebug( BaseMessages.getString( PKG, "TransStatusServlet.Log.TransStatusRequested" ) ); } String transName = request.getParameter( "name" ); String id = request.getParameter( "id" ); String root = request.getRequestURI() == null ? StatusServletUtils.PENTAHO_ROOT : request.getRequestURI().substring( 0, request.getRequestURI().indexOf( CONTEXT_PATH ) ); String prefix = isJettyMode() ? StatusServletUtils.STATIC_PATH : root + StatusServletUtils.RESOURCES_PATH; boolean useXML = "Y".equalsIgnoreCase( request.getParameter( "xml" ) ); int startLineNr = Const.toInt( request.getParameter( "from" ), 0 ); response.setStatus( HttpServletResponse.SC_OK ); if ( useXML ) { response.setContentType( "text/xml" ); response.setCharacterEncoding( Const.XML_ENCODING ); } else { response.setCharacterEncoding( "UTF-8" ); response.setContentType( "text/html;charset=UTF-8" ); } // ID is optional... // Trans trans; CarteObjectEntry entry; if ( Utils.isEmpty( id ) ) { // get the first transformation that matches... // entry = getTransformationMap().getFirstCarteObjectEntry( transName ); if ( entry == null ) { trans = null; } else { id = entry.getId(); trans = getTransformationMap().getTransformation( entry ); } } else { // Take the ID into account! // entry = new CarteObjectEntry( transName, id ); trans = getTransformationMap().getTransformation( entry ); } if ( trans != null ) { if ( useXML ) { try { OutputStream out = null; byte[] data = null; String logId = trans.getLogChannelId(); boolean finishedOrStopped = trans.isFinishedOrStopped(); boolean sendResultXmlWithStatus = "Y".equalsIgnoreCase( request.getParameter( SEND_RESULT ) ); boolean dontUseCache = sendResultXmlWithStatus; if ( finishedOrStopped && ( data = cache.get( logId, startLineNr ) ) != null && !dontUseCache ) { response.setContentLength( XML_HEADER.length + data.length ); out = response.getOutputStream(); out.write( XML_HEADER ); out.write( data ); out.flush(); } else { int lastLineNr = KettleLogStore.getLastBufferLineNr(); String logText = getLogText( trans, startLineNr, lastLineNr ); response.setContentType( "text/xml" ); response.setCharacterEncoding( Const.XML_ENCODING ); SlaveServerTransStatus transStatus = new SlaveServerTransStatus( transName, entry.getId(), trans.getStatus() ); transStatus.setFirstLoggingLineNr( startLineNr ); transStatus.setLastLoggingLineNr( lastLineNr ); transStatus.setLogDate( trans.getLogDate() ); for ( int i = 0; i < trans.nrSteps(); i++ ) { StepInterface baseStep = trans.getRunThread( i ); if ( ( baseStep.isRunning() ) || baseStep.getStatus() != StepExecutionStatus.STATUS_EMPTY ) { StepStatus stepStatus = new StepStatus( baseStep ); transStatus.getStepStatusList().add( stepStatus ); } } // The log can be quite large at times, we are going to putIfAbsent a base64 encoding around a compressed // stream // of bytes to handle this one. String loggingString = HttpUtil.encodeBase64ZippedString( logText ); transStatus.setLoggingString( loggingString ); // transStatus.setLoggingUncompressedSize( logText.length() ); // Also set the result object... // transStatus.setResult( trans.getResult() ); // Is the transformation paused? // transStatus.setPaused( trans.isPaused() ); // Send the result back as XML // String xml = transStatus.getXML( sendResultXmlWithStatus ); data = xml.getBytes( Charset.forName( Const.XML_ENCODING ) ); out = response.getOutputStream(); response.setContentLength( XML_HEADER.length + data.length ); out.write( XML_HEADER ); out.write( data ); out.flush(); if ( finishedOrStopped && ( transStatus.isFinished() || transStatus.isStopped() ) && logId != null && !dontUseCache ) { cache.put( logId, xml, startLineNr ); } } response.flushBuffer(); } catch ( KettleException e ) { throw new ServletException( "Unable to get the transformation status in XML format", e ); } } else { PrintWriter out = response.getWriter(); int lastLineNr = KettleLogStore.getLastBufferLineNr(); int tableBorder = 0; response.setContentType( "text/html;charset=UTF-8" ); out.println( "" ); out.println( "" ); out.println( "" + BaseMessages.getString( PKG, "TransStatusServlet.KettleTransStatus" ) + "" ); if ( EnvUtil.getSystemProperty( Const.KETTLE_CARTE_REFRESH_STATUS, "N" ).equalsIgnoreCase( "Y" ) ) { out.println( "" ); } out.println( "" ); if ( isJettyMode() ) { out.println( "" ); } else { out.print( StatusServletUtils.getPentahoStyles( root ) ); } out.println( "" ); out.println( "" ); out.println( "
" ); out.println( "
" + Encode.forHtml( BaseMessages.getString( PKG, "TransStatusServlet.TopTransStatus", transName ) ) + "
" ); out.println( "
" ); try { out.println( "
" ); out.println( "" ); out.println( "
" ); out.println( "
" ); out.println( "
" ); out.println( "" ); out.println( "
" ); out.println( "
" ); out.println( "" ); out.print( "" ); out.print( "" ); out.print( "" ); out.print( "" ); String dateStr = XMLHandler.date2string( trans.getLogDate() ); out.print( "" ); out.print( "" ); out.print( "
" + BaseMessages.getString( PKG, "TransStatusServlet.CarteObjectId" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.TransStatus" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.LastLogDate" ) + "
" + Encode.forHtml( id ) + "" + Encode.forHtml( trans.getStatus() ) + "" + dateStr.substring( 0, dateStr.indexOf( ' ' ) ) + "
" ); out.print( "
" ); out.println( "
" ); out.print( "
" ); out.print( "" + "" ); out.print( "
" ); out.println( "" ); out.print( "
" ); out.print( "
" ); out.print( "
" ); out.print( "
" ); out.print( "
Step detail
" ); out.println( "" ); out.print( "" ); boolean evenRow = true; for ( int i = 0; i < trans.nrSteps(); i++ ) { StepInterface step = trans.getRunThread( i ); if ( ( step.isRunning() ) || step.getStatus() != StepExecutionStatus.STATUS_EMPTY ) { StepStatus stepStatus = new StepStatus( step ); boolean snif = false; String htmlString = ""; if ( step.isRunning() && !step.isStopped() && !step.isPaused() ) { snif = true; String sniffLink = " " + Encode.forHtml( stepStatus.getStepname() ) + ""; stepStatus.setStepname( sniffLink ); } String rowClass = evenRow ? "cellTableEvenRow" : "cellTableOddRow"; String cellClass = evenRow ? "cellTableEvenRowCell" : "cellTableOddRowCell"; htmlString = "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; evenRow = !evenRow; out.print( htmlString ); } } out.println( "
" + BaseMessages.getString( PKG, "TransStatusServlet.Stepname" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.CopyNr" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Read" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Written" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Input" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Output" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Updated" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Rejected" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Errors" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Active" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Time" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.Speed" ) + " " + BaseMessages.getString( PKG, "TransStatusServlet.prinout" ) + "
" + stepStatus.getStepname() + "" + stepStatus.getCopy() + "" + stepStatus.getLinesRead() + "" + stepStatus.getLinesWritten() + "" + stepStatus.getLinesInput() + "" + stepStatus.getLinesOutput() + "" + stepStatus.getLinesUpdated() + "" + stepStatus.getLinesRejected() + "" + stepStatus.getErrors() + "" + stepStatus.getStatusDescription() + "" + stepStatus.getSeconds() + "" + stepStatus.getSpeed() + "" + stepStatus.getPriority() + "
" ); out.println( "
" ); out.print( "
" ); out.print( "
Canvas preview
" ); // Get the transformation image // // out.print("" // + BaseMessages.getString(PKG, "TransStatusServlet.GetTransImage") + ""); Point max = trans.getTransMeta().getMaximum(); max.x += 20; max.y += 20; out.print( "" ); out.print( "
" ); // Put the logging below that. out.print( "
" ); out.print( "
Transformation log
" ); out .println( "" ); out.print( "
" ); out.println( "" ); out.println( " " ); } catch ( Exception ex ) { out.println( "
" );
          out.println( Encode.forHtml( Const.getStackTracker( ex ) ) );
          out.println( "
" ); } out.println( "
" ); out.println( "" ); out.println( "" ); } } else { PrintWriter out = response.getWriter(); if ( useXML ) { out.println( new WebResult( WebResult.STRING_ERROR, BaseMessages.getString( PKG, "TransStatusServlet.Log.CoundNotFindSpecTrans", transName ) ) ); } else { out.println( "

" + Encode.forHtml( BaseMessages.getString( PKG, "TransStatusServlet.Log.CoundNotFindTrans", transName ) ) + "

" ); out.println( "" + BaseMessages.getString( PKG, "TransStatusServlet.BackToStatusPage" ) + "

" ); } } } public String toString() { return "Trans Status Handler"; } public String getService() { return CONTEXT_PATH + " (" + toString() + ")"; } public String getContextPath() { return CONTEXT_PATH; } private String getLogText( Trans trans, int startLineNr, int lastLineNr ) throws KettleException { try { return KettleLogStore.getAppender().getBuffer( trans.getLogChannel().getLogChannelId(), false, startLineNr, lastLineNr ).toString(); } catch ( OutOfMemoryError error ) { throw new KettleException( "Log string is too long", error ); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy