org.kawanfw.sql.servlet.executor.ServerSqlExecutorCallable.java Source code

Java tutorial

Introduction

Here is the source code for org.kawanfw.sql.servlet.executor.ServerSqlExecutorCallable.java

Source

/*
 * This file is part of AceQL. 
 * AceQL: Remote JDBC access over HTTP.                                     
 * Copyright (C) 2015,  KawanSoft SAS
 * (http://www.kawansoft.com). All rights reserved.                                
 *                                                                               
 * AceQL is free software; you can redistribute it and/or                 
 * modify it under the terms of the GNU Lesser General Public                    
 * License as published by the Free Software Foundation; either                  
 * version 2.1 of the License, or (at your option) any later version.            
 *                                                                               
 * AceQL is distributed in the hope that it will be useful,               
 * but WITHOUT ANY WARRANTY; without even the implied warranty of                
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU             
 * Lesser General Public License for more details.                               
 *                                                                               
 * You should have received a copy of the GNU Lesser General Public              
 * License along with this library; if not, write to the Free Software           
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
 * 02110-1301  USA
 *
 * Any modifications to this file must keep this entire header
 * intact.
 */
package org.kawanfw.sql.servlet.executor;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.kawanfw.commons.api.server.CommonsConfigurator;
import org.kawanfw.commons.server.util.ServerLogger;
import org.kawanfw.commons.util.FrameworkDebug;
import org.kawanfw.commons.util.Tag;
import org.kawanfw.commons.util.TransferStatus;
import org.kawanfw.file.api.server.FileConfigurator;
import org.kawanfw.file.servlet.util.HttpConfigurationUtil;
import org.kawanfw.file.util.parms.Parameter;
import org.kawanfw.sql.api.server.SqlConfigurator;
import org.kawanfw.sql.json.no_obfuscation.CallableStatementHolder;
import org.kawanfw.sql.servlet.ConnectionCloser;
import org.kawanfw.sql.servlet.ServerSqlManager;
import org.kawanfw.sql.servlet.connection.ConnectionStore;
import org.kawanfw.sql.servlet.sql.CallableStatementHolderListReader;
import org.kawanfw.sql.servlet.sql.ServerCallableStatement;
import org.kawanfw.sql.servlet.sql.ServerSqlUtil;
import org.kawanfw.sql.servlet.sql.ServerStatement;
import org.kawanfw.sql.transport.TransportConverter;
import org.kawanfw.sql.util.ConnectionParms;
import org.kawanfw.sql.util.SqlAction;
import org.kawanfw.sql.util.SqlReturnCode;
import org.kawanfw.sql.util.crypto.CallableStatementHolderListDecryptor;

/**
 * Execute transported statements on the server
 * 
 * @author Nicolas de Pomereu
 * 
 */
public class ServerSqlExecutorCallable {
    private static boolean DEBUG = FrameworkDebug.isSet(ServerSqlExecutorCallable.class);

    // When executing a non-query (Prepared) Statement
    public static final String STATEMENT_NORMAL_EXECUTED = "0";

    private HttpServletRequest request = null;
    private OutputStream out = null;

    private CommonsConfigurator commonsConfigurator = null;
    private FileConfigurator fileConfigurator = null;
    private SqlConfigurator sqlConfigurator = null;

    /** If true, we will ask to to a raw CallableStatement.execute() */
    private boolean isExecuteRaw = false;

    /**
     * Constructor
     * 
     * @param request
     *            the servlet http request
     * @param out
     *            the servlet output stream
     * @param fileConfigurator
     *            the FILE Configurator
     * @param commonsConfigurator
     *            the Commons Configurator
     * @param sqlConfigurator
     *            the SQL Configurator
     */
    public ServerSqlExecutorCallable(HttpServletRequest request, OutputStream out,
            CommonsConfigurator commonsConfigurator, FileConfigurator fileConfigurator,
            SqlConfigurator sqlConfigurator)

    {
        this.request = request;
        this.out = out;

        this.commonsConfigurator = commonsConfigurator;
        this.fileConfigurator = fileConfigurator;
        this.sqlConfigurator = sqlConfigurator;

    }

    /**
     * Will call a list of CallableStatement.executeQuery()
     * 
     * @throws IOException
     * @throws SQLException
     * @throws IllegalArgumentException
     */
    public void executeQuery() throws IOException, SQLException, IllegalArgumentException {
        isExecuteRaw = false;
        callStatement();
    }

    /**
     * Will call a list of CallableStatement.execute()
     * 
     * @throws IOException
     * @throws SQLException
     * @throws IllegalArgumentException
     */
    public void execute() throws IOException, SQLException, IllegalArgumentException {
        isExecuteRaw = true;
        callStatement();
    }

    /**
     * Execute the Callable Statement
     * 
     * @throws IOException
     * @throws SQLException
     * @throws IllegalArgumentException
     */
    public void callStatement() throws IOException, SQLException, IllegalArgumentException {
        String username = request.getParameter(Parameter.USERNAME);
        String connectionId = request.getParameter(ConnectionParms.CONNECTION_ID);

        String conHolderParam = request.getParameter(SqlAction.CONNECTION_HOLDER);
        String statementHolderParam = request.getParameter(SqlAction.STATEMENT_HOLDER);

        debug("SqlAction.CONNECTION_HOLDER: " + conHolderParam);
        debug("SqlAction.STATEMENT_HOLDER : " + statementHolderParam);

        Connection connection = null;
        List<File> tempFilesForResultSet = new Vector<File>();

        if (connectionId.equals("0")) {
            // stateless mode was set on PC
            try {
                connection = commonsConfigurator.getConnection();
                ServerSqlUtil.setConnectionProperties(conHolderParam, connection);

                if (statementHolderParam.startsWith(TransportConverter.KAWANFW_BYTES_STREAM_FILE)) {
                    String fileName = StringUtils.substringAfter(statementHolderParam,
                            TransportConverter.KAWANFW_BYTES_STREAM_FILE);
                    // Param contains only the file to read from the statements
                    callStatementsFromFile(username, fileName, connection, tempFilesForResultSet);
                } else {
                    // All statements are in single param
                    callStatementsFromList(username, statementHolderParam, connection, tempFilesForResultSet);
                }

                if (!connection.getAutoCommit()) {
                    connection.commit();
                }
            } catch (IOException e) {
                if (!connection.getAutoCommit()) {
                    connection.rollback();
                }

                throw e;
            } catch (SQLException e) {
                if (!connection.getAutoCommit()) {
                    connection.rollback();
                }

                throw e;
            } finally {
                // Release the connection
                ConnectionCloser.freeConnection(connection, sqlConfigurator);
            }
        } else {

            ConnectionStore connectionStore = new ConnectionStore(username, connectionId);
            connection = connectionStore.get();

            if (connection == null) {
                //out.println(TransferStatus.SEND_OK);
                //out.println(SqlReturnCode.SESSION_INVALIDATED);
                ServerSqlManager.writeLine(out, TransferStatus.SEND_OK);
                ServerSqlManager.writeLine(out, SqlReturnCode.SESSION_INVALIDATED);
                return;
            }

            if (statementHolderParam.startsWith(TransportConverter.KAWANFW_BYTES_STREAM_FILE)) {
                String fileName = StringUtils.substringAfter(statementHolderParam,
                        TransportConverter.KAWANFW_BYTES_STREAM_FILE);
                // Param contains only the file to read from the statements
                callStatementsFromFile(username, fileName, connection, tempFilesForResultSet);
            } else {
                // All statements are in single param
                callStatementsFromList(username, statementHolderParam, connection, tempFilesForResultSet);
            }
        }

        // Of, if the list is not empty, dump it to out on servlet out stream
        FileDumper.dumpFile(tempFilesForResultSet, out);

    }

    private void callStatementsFromList(String username, String statementHolderParam, Connection connection,
            List<File> tempFilesForResultSet) throws SQLException, IOException {
        // All statements are in param

        List<CallableStatementHolder> callableStatementHolderList = CallableStatementHolderListDecryptor
                .decryptFromJson(statementHolderParam, commonsConfigurator);

        File file = ServerStatement.createTempFileForResultSet();

        for (CallableStatementHolder callableStatementHolder : callableStatementHolderList) {

            ServerCallableStatement serverStatement = new ServerCallableStatement(request, commonsConfigurator,
                    fileConfigurator, sqlConfigurator, connection, username, callableStatementHolder, isExecuteRaw);

            serverStatement.execute(file);

        } // end for

        tempFilesForResultSet.add(file);
    }

    private void callStatementsFromFile(String username, String fileName, Connection connection,
            List<File> tempFilesForResultSet) throws SQLException, IOException {
        fileName = HttpConfigurationUtil.addRootPath(fileConfigurator, username, fileName);

        File file = new File(fileName);

        if (!file.exists()) {
            throw new IOException(Tag.PRODUCT_PRODUCT_FAIL
                    + "The file corresponding to a list of Statements does not exist on remote Server: "
                    + fileName);
        }

        CallableStatementHolder callableStatementHolder = null;

        CallableStatementHolderListReader callableStatementHolderListReader = null;

        callableStatementHolderListReader = new CallableStatementHolderListReader(file, commonsConfigurator);

        try {

            File fileExecute = ServerStatement.createTempFileForResultSet();

            // boolean isFistStatement = true;

            while ((callableStatementHolder = callableStatementHolderListReader.readLine()) != null) {

                ServerCallableStatement serverStatement = new ServerCallableStatement(request, commonsConfigurator,
                        fileConfigurator, sqlConfigurator, connection, username, callableStatementHolder,
                        isExecuteRaw);

                // if (!callableStatementHolder.isExecuteUpdate()) {
                // serverStatement.execute(fileExecute);
                // } else {
                // // In case of execute update, we store only the first
                // // result of
                // // the list of statements
                // if (isFistStatement) {
                // serverStatement.execute(fileExecute);
                // } else {
                // serverStatement.execute();
                // }
                // }

                // This is not an execute update, so we execute on file:
                serverStatement.execute(fileExecute);

                // isFistStatement = false;
            }

            tempFilesForResultSet.add(fileExecute);

        } finally {
            if (callableStatementHolderListReader != null) {
                callableStatementHolderListReader.close();
                callableStatementHolderListReader = null;
            }
        }

    }

    /**
     * Method called by children Servlest for debug purpose Println is done only
     * if class name name is in kawansoft-debug.ini
     */
    public static void debug(String s) {
        if (DEBUG) {
            ServerLogger.getLogger().log(Level.WARNING, s);
        }
    }

}