/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2013 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;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.logging.LogChannelFileWriter;
import org.pentaho.di.core.logging.LoggingObjectType;
import org.pentaho.di.core.logging.SimpleLoggingObject;
import org.pentaho.di.core.util.FileUtil;
import org.pentaho.di.core.vfs.KettleVFS;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransAdapter;
import org.pentaho.di.trans.TransConfiguration;
import org.pentaho.di.trans.TransExecutionConfiguration;
import org.pentaho.di.trans.TransMeta;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//has been replaced by RegisterTransServlet
@Deprecated
public class AddTransServlet extends BaseHttpServlet implements CartePluginInterface {
private static final long serialVersionUID = -6850701762586992604L;
public static final String CONTEXT_PATH = "/kettle/addTrans";
public AddTransServlet() {
}
public AddTransServlet( TransformationMap transformationMap, SocketRepository socketRepository ) {
super( transformationMap, socketRepository );
}
/**
<div id="mindtouch">
<h1>/kettle/addTrans</h1>
<a name="POST"></a>
<h2>POST</h2>
<p>Uploads and executes transformation configuration XML file.
Uploads xml file containing transformation and transformation_execution_configuration
(wrapped in transformation_configuration tag) to be executed and executes it. Method relies
on the input parameter to determine if xml or html reply should be produced. The transformation_configuration xml is
transferred within request body.
<code>transformation name of the executed transformation </code> will be returned in the Response object
or <code>message</code> describing error occurred. To determine if the call successful or not you should
rely on <code>result</code> parameter in response.</p>
<p><b>Example Request:</b><br />
<pre function="syntax.xml">
POST /kettle/addTrans/?xml=Y
</pre>
<p>Request body should contain xml containing transformation_configuration (transformation and
transformation_execution_configuration wrapped in transformation_configuration tag).</p>
</p>
<h3>Parameters</h3>
<table class="pentaho-table">
<tbody>
<tr>
<th>name</th>
<th>description</th>
<th>type</th>
</tr>
<tr>
<td>xml</td>
<td>Boolean flag set to either <code>Y</code> or <code>N</code> describing if xml or html reply
should be produced.</td>
<td>boolean, optional</td>
</tr>
</tbody>
</table>
<h3>Response Body</h3>
<table class="pentaho-table">
<tbody>
<tr>
<td align="right">element:</td>
<td>(custom)</td>
</tr>
<tr>
<td align="right">media types:</td>
<td>text/xml, text/html</td>
</tr>
</tbody>
</table>
<p>Response wraps transformation name that was executed or error stack trace
if an error occurred. Response has <code>result</code> OK if there were no errors. Otherwise it returns ERROR.</p>
<p><b>Example Response:</b></p>
<pre function="syntax.xml">
<?xml version="1.0" encoding="UTF-8"?>
<webresult>
<result>OK</result>
<message>Transformation 'dummy-trans' was added to Carte with id eb4a92ff-6852-4307-9f74-3c74bd61f829</message>
<id>eb4a92ff-6852-4307-9f74-3c74bd61f829</id>
</webresult>
</pre>
<h3>Status Codes</h3>
<table class="pentaho-table">
<tbody>
<tr>
<th>code</th>
<th>description</th>
</tr>
<tr>
<td>200</td>
<td>Request was processed and XML response is returned.</td>
</tr>
<tr>
<td>500</td>
<td>Internal server error occurs during request processing.</td>
</tr>
</tbody>
</table>
</div>
*/
public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
IOException {
if ( isJettyMode() && !request.getRequestURI().startsWith( CONTEXT_PATH ) ) {
return;
}
if ( log.isDebug() ) {
logDebug( "Addition of transformation requested" );
}
boolean useXML = "Y".equalsIgnoreCase( request.getParameter( "xml" ) );
PrintWriter out = response.getWriter();
BufferedReader in = request.getReader();
if ( log.isDetailed() ) {
logDetailed( "Encoding: " + request.getCharacterEncoding() );
}
if ( useXML ) {
response.setContentType( "text/xml" );
out.print( XMLHandler.getXMLHeader() );
} else {
response.setContentType( "text/html" );
out.println( "<HTML>" );
out.println( "<HEAD><TITLE>Add transformation</TITLE></HEAD>" );
out.println( "<BODY>" );
}
response.setStatus( HttpServletResponse.SC_OK );
String realLogFilename = null;
TransExecutionConfiguration transExecutionConfiguration = null;
try {
// First read the complete transformation in memory from the request
//
StringBuilder xml = new StringBuilder( request.getContentLength() );
int c;
while ( ( c = in.read() ) != -1 ) {
xml.append( (char) c );
}
// Parse the XML, create a transformation configuration
//
TransConfiguration transConfiguration = TransConfiguration.fromXML( xml.toString() );
TransMeta transMeta = transConfiguration.getTransMeta();
transExecutionConfiguration = transConfiguration.getTransExecutionConfiguration();
transMeta.setLogLevel( transExecutionConfiguration.getLogLevel() );
if ( log.isDetailed() ) {
logDetailed( "Logging level set to " + log.getLogLevel().getDescription() );
}
transMeta.injectVariables( transExecutionConfiguration.getVariables() );
// Also copy the parameters over...
//
Map<String, String> params = transExecutionConfiguration.getParams();
for ( String param : params.keySet() ) {
String value = params.get( param );
transMeta.setParameterValue( param, value );
}
// If there was a repository, we know about it at this point in time.
//
final Repository repository = transExecutionConfiguration.getRepository();
String carteObjectId = UUID.randomUUID().toString();
SimpleLoggingObject servletLoggingObject =
new SimpleLoggingObject( CONTEXT_PATH, LoggingObjectType.CARTE, null );
servletLoggingObject.setContainerObjectId( carteObjectId );
servletLoggingObject.setLogLevel( transExecutionConfiguration.getLogLevel() );
// Create the transformation and store in the list...
//
final Trans trans = new Trans( transMeta, servletLoggingObject );
if ( transExecutionConfiguration.isSetLogfile() ) {
realLogFilename = transExecutionConfiguration.getLogFileName();
final LogChannelFileWriter logChannelFileWriter;
try {
FileUtil.createParentFolder( AddTransServlet.class, realLogFilename, transExecutionConfiguration
.isCreateParentFolder(), trans.getLogChannel(), trans );
logChannelFileWriter =
new LogChannelFileWriter( servletLoggingObject.getLogChannelId(), KettleVFS
.getFileObject( realLogFilename ), transExecutionConfiguration.isSetAppendLogfile() );
logChannelFileWriter.startLogging();
trans.addTransListener( new TransAdapter() {
@Override
public void transFinished( Trans trans ) throws KettleException {
if ( logChannelFileWriter != null ) {
logChannelFileWriter.stopLogging();
}
}
} );
} catch ( KettleException e ) {
logError( Const.getStackTracker( e ) );
}
}
trans.setRepository( repository );
trans.setSocketRepository( getSocketRepository() );
getTransformationMap().addTransformation( transMeta.getName(), carteObjectId, trans, transConfiguration );
trans.setContainerObjectId( carteObjectId );
if ( repository != null ) {
// The repository connection is open: make sure we disconnect from the repository once we
// are done with this transformation.
//
trans.addTransListener( new TransAdapter() {
public void transFinished( Trans trans ) {
repository.disconnect();
}
} );
}
String message = "Transformation '" + trans.getName() + "' was added to Carte with id " + carteObjectId;
if ( useXML ) {
// Return the log channel id as well
//
out.println( new WebResult( WebResult.STRING_OK, message, carteObjectId ) );
} else {
out.println( "<H1>" + message + "</H1>" );
out.println( "<p><a href=\""
+ convertContextPath( GetTransStatusServlet.CONTEXT_PATH ) + "?name=" + trans.getName() + "&id="
+ carteObjectId + "\">Go to the transformation status page</a><p>" );
}
} catch ( Exception ex ) {
if ( useXML ) {
out.println( new WebResult( WebResult.STRING_ERROR, Const.getStackTracker( ex ) ) );
} else {
out.println( "<p>" );
out.println( "<pre>" );
ex.printStackTrace( out );
out.println( "</pre>" );
}
}
if ( !useXML ) {
out.println( "<p>" );
out.println( "</BODY>" );
out.println( "</HTML>" );
}
}
public String toString() {
return "Add Transformation";
}
public String getService() {
return CONTEXT_PATH + " (" + toString() + ")";
}
public String getContextPath() {
return CONTEXT_PATH;
}
}