org.pentaho.di.trans.dataservice.jdbc.RemoteClient.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.trans.dataservice.jdbc.RemoteClient.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.jdbc;

import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.pentaho.di.core.row.RowMeta;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.trans.dataservice.client.DataServiceClientService;
import org.pentaho.metastore.api.IMetaStore;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.DataInputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author nhudak
 */
class RemoteClient implements DataServiceClientService {

    private static final String SQL = "SQL";
    private static final String MAX_ROWS = "MaxRows";
    private static final int MAX_SQL_LENGTH = 7500;

    private final ThinConnection connection;
    private final HttpClient client;
    private DocumentBuilderFactory docBuilderFactory;
    private static final String SERVICE_PATH = "/sql/";

    RemoteClient(ThinConnection connection, HttpClient client) {
        this.connection = connection;
        this.client = client;
    }

    @Override
    public DataInputStream query(String sql, int maxRows) throws SQLException {
        try {
            String url = connection.constructUrl(SERVICE_PATH);
            PostMethod method = new PostMethod(url);
            method.setDoAuthentication(true);

            method.getParams().setParameter("http.socket.timeout", 0);

            // Kept in for backwards compatibility, but should be removed in next major release
            if (sql.length() < MAX_SQL_LENGTH) {
                method.addRequestHeader(new Header(SQL, CharMatcher.anyOf("\n\r").collapseFrom(sql, ' ')));
                method.addRequestHeader(new Header(MAX_ROWS, Integer.toString(maxRows)));
            }
            method.addParameter(SQL, CharMatcher.anyOf("\n\r").collapseFrom(sql, ' '));
            method.addParameter(MAX_ROWS, Integer.toString(maxRows));

            for (Map.Entry<String, String> parameterEntry : connection.getParameters().entrySet()) {
                method.addParameter(parameterEntry.getKey(), parameterEntry.getValue());
            }
            if (!Strings.isNullOrEmpty(connection.getDebugTransFilename())) {
                method.addParameter(ThinConnection.ARG_DEBUGTRANS, connection.getDebugTransFilename());
            }

            return new DataInputStream(execMethod(method).getResponseBodyAsStream());
        } catch (Exception e) {
            throw serverException(e);
        }
    }

    @Override
    public List<ThinServiceInformation> getServiceInformation() throws SQLException {
        List<ThinServiceInformation> services = Lists.newArrayList();

        try {
            String result = execService("/listServices");
            Document doc = XMLHandler.loadXMLString(createDocumentBuilder(), result);
            Node servicesNode = XMLHandler.getSubNode(doc, "services");
            List<Node> serviceNodes = XMLHandler.getNodes(servicesNode, "service");

            for (Node serviceNode : serviceNodes) {
                String name = XMLHandler.getTagValue(serviceNode, "name");
                Node rowMetaNode = XMLHandler.getSubNode(serviceNode, RowMeta.XML_META_TAG);
                RowMetaInterface serviceFields = new RowMeta(rowMetaNode);
                ThinServiceInformation service = new ThinServiceInformation(name, serviceFields);
                services.add(service);
            }
        } catch (Exception e) {
            throw serverException(e);
        }

        return services;
    }

    @Override
    public ThinServiceInformation getServiceInformation(String name) throws SQLException {
        try {
            String result = execService("/listServices");
            Document doc = XMLHandler.loadXMLString(createDocumentBuilder(), result);
            Node servicesNode = XMLHandler.getSubNode(doc, "services");
            List<Node> serviceNodes = XMLHandler.getNodes(servicesNode, "service");

            for (Node serviceNode : serviceNodes) {
                String serviceName = XMLHandler.getTagValue(serviceNode, "name");
                if (serviceName.equals(name)) {
                    Node rowMetaNode = XMLHandler.getSubNode(serviceNode, RowMeta.XML_META_TAG);
                    RowMetaInterface serviceFields = new RowMeta(rowMetaNode);
                    return new ThinServiceInformation(serviceName, serviceFields);
                }
            }

        } catch (Exception e) {
            throw serverException(e);
        }

        return null;
    }

    @Override
    public List<String> getServiceNames(String serviceName) throws SQLException {
        return getServiceNames();
    }

    @Override
    public List<String> getServiceNames() throws SQLException {
        List<String> serviceNames = new ArrayList<String>();
        try {
            String result = execService("/listServices");
            Document doc = XMLHandler.loadXMLString(createDocumentBuilder(), result);
            Node servicesNode = XMLHandler.getSubNode(doc, "services");
            List<Node> serviceNodes = XMLHandler.getNodes(servicesNode, "service");

            for (Node serviceNode : serviceNodes) {
                String serviceName = XMLHandler.getTagValue(serviceNode, "name");
                serviceNames.add(serviceName);
            }
        } catch (Exception e) {
            throw serverException(e);
        }
        return serviceNames;
    }

    private DocumentBuilder createDocumentBuilder() throws ParserConfigurationException {
        if (docBuilderFactory == null) {
            docBuilderFactory = DocumentBuilderFactory.newInstance();
        }
        return docBuilderFactory.newDocumentBuilder();
    }

    String execService(String serviceAndArguments) throws SQLException {
        try {
            String urlString = connection.constructUrl(serviceAndArguments);
            HttpMethod method = new GetMethod(urlString);

            try {
                return execMethod(method).getResponseBodyAsString();
            } finally {
                method.releaseConnection();
            }

        } catch (Exception e) {
            throw serverException(e);
        }
    }

    HttpMethod execMethod(HttpMethod method) throws SQLException {
        try {
            int result = client.executeMethod(method);

            if (result == 500) {
                throw new SQLException("There was an error reading data from the server.");
            }

            if (result == 401) {
                throw new SQLException(
                        "Nice try-but we couldn't log you in. Check your username and password and try again.");
            }

            if (result != 200) {
                throw new SQLException(method.getResponseBodyAsString());
            }
        } catch (IOException e) {
            throw new SQLException(
                    "You don't seem to be getting a connection to the server. Check the host and port you're using and make sure the sever is up and running.");
        }
        return method;
    }

    private static SQLException serverException(Exception e) throws SQLException {
        Throwables.propagateIfPossible(e, SQLException.class);
        throw new SQLException("Error connecting to server", e);
    }

    @Deprecated
    public void setRepository(Repository repository) {
    }

    @Deprecated
    public void setMetaStore(IMetaStore metaStore) {
    }
}