org.pentaho.di.trans.dataservice.www.TransDataServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.trans.dataservice.www.TransDataServlet.java

Source

/*! ******************************************************************************
 *
 * 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.trans.dataservice.www;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.annotations.CarteServlet;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransConfiguration;
import org.pentaho.di.trans.TransExecutionConfiguration;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.dataservice.clients.DataServiceClient;
import org.pentaho.di.trans.dataservice.clients.Query;
import org.pentaho.di.www.BaseCartePlugin;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * This servlet allows a user to get data from a "service" which is a transformation step.
 *
 * @author matt
 */
@CarteServlet(id = "sql", name = "Get data from a data service", description = "Get data from a transformation data service using SQL")
public class TransDataServlet extends BaseCartePlugin {
    private static final long serialVersionUID = 3634806745372015720L;

    public static final String PARAMETER_PREFIX = "PARAMETER_";

    private static final String MAX_ROWS = "MaxRows";
    private static final String SQL = "SQL";
    private final DataServiceClient client;

    public static final String CONTEXT_PATH = "/sql";

    public TransDataServlet(DataServiceClient client) {
        this.client = client;
        this.log = client.getLogChannel();
    }

    public void handleRequest(CarteRequest request) throws IOException {
        String sqlQuery = !Strings.isNullOrEmpty(request.getParameter(SQL)) ? request.getParameter(SQL)
                : request.getHeader(SQL);
        if (Strings.isNullOrEmpty(sqlQuery)) {

            String sqlParamMissing = "SQL not specified";
            logError(sqlParamMissing);
            request.respond(400).withMessage(sqlParamMissing);
            return;
        }
        String maxRowsValue = !Strings.isNullOrEmpty(request.getParameter(MAX_ROWS))
                ? request.getParameter(MAX_ROWS)
                : request.getHeader(MAX_ROWS);
        final int maxRows = Const.toInt(maxRowsValue, -1);

        final String debugTransFile = request.getParameter("debugtrans");

        Map<String, String> parameters = collectParameters(request.getParameters());
        try {
            final Query query = client.prepareQuery(sqlQuery, maxRows, parameters);

            // For logging and tracking purposes, let's expose both the service transformation as well
            // as the generated transformation on this very carte instance
            List<Trans> transList = query.getTransList();
            for (Trans trans : transList) {
                monitorTransformation(trans);
            }

            if (!Strings.isNullOrEmpty(debugTransFile) && !transList.isEmpty()) {
                saveGeneratedTransformation(Iterables.getLast(transList).getTransMeta(), debugTransFile);
            }

            request.respond(200).with("binary/jdbc", new OutputStreamResponse() {
                @Override
                public void write(OutputStream outputStream) throws IOException {
                    query.writeTo(outputStream);
                }
            });

        } catch (Exception e) {
            logError("Error executing SQL query: " + sqlQuery, e);
            request.respond(400).withMessage(Strings.nullToEmpty(e.getMessage()).trim());
        }
    }

    private void monitorTransformation(Trans trans) {
        TransMeta transMeta = trans.getTransMeta();
        TransExecutionConfiguration executionConfiguration = new TransExecutionConfiguration();
        TransConfiguration config = new TransConfiguration(transMeta, executionConfiguration);
        transformationMap.addTransformation(transMeta.getName(), trans.getContainerObjectId(), trans, config);
    }

    private void saveGeneratedTransformation(TransMeta genTransMeta, String debugTrans) {
        try {
            FileOutputStream fos = new FileOutputStream(debugTrans);
            fos.write(XMLHandler.getXMLHeader(Const.XML_ENCODING).getBytes(Const.XML_ENCODING));
            fos.write(genTransMeta.getXML().getBytes(Const.XML_ENCODING));
            fos.close();
        } catch (Exception e) {
            logError("Unable to write dynamic transformation to file", e);
        }
    }

    public String getContextPath() {
        return CONTEXT_PATH;
    }

    private Map<String, String> collectParameters(Map<String, Collection<String>> map) {
        Map<String, String> parameters = Maps.newHashMap();
        for (Map.Entry<String, Collection<String>> parameterEntry : map.entrySet()) {
            String name = parameterEntry.getKey();
            Iterator<String> value = parameterEntry.getValue().iterator();
            if (name.startsWith(PARAMETER_PREFIX) && value.hasNext()) {
                String firstVal = value.next();
                parameters.put(name.substring(PARAMETER_PREFIX.length()), firstVal);
                if (value.hasNext()) {
                    logDetailed(String.format(
                            "More than one value associated with param %s.  Setting to first found (%s)", name,
                            firstVal));
                }
            }
        }
        return ImmutableMap.copyOf(parameters);
    }

}