![JAR search and dependency download from the Maven repository](/logo.png)
org.kawanfw.sql.servlet.ServerSqlDispatch Maven / Gradle / Ivy
/*
* 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;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.logging.Level;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.exception.ExceptionUtils;
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.KawanNotifier;
import org.kawanfw.file.servlet.ServerFileDispatch;
import org.kawanfw.file.servlet.ServerFileUploadAction;
import org.kawanfw.file.servlet.ServerUserThrowable;
import org.kawanfw.file.util.parms.Action;
import org.kawanfw.file.util.parms.Parameter;
import org.kawanfw.file.util.parms.ReturnCode;
import org.kawanfw.sql.api.server.SqlConfigurator;
import org.kawanfw.sql.servlet.connection.ConnectionInfoUtil;
import org.kawanfw.sql.servlet.connection.ConnectionStore;
import org.kawanfw.sql.servlet.connection.ConnectionStoreCleaner;
import org.kawanfw.sql.servlet.connection.SavepointUtil;
import org.kawanfw.sql.servlet.connection.TransactionUtil;
import org.kawanfw.sql.servlet.executor.ServerBatchPrepStatementExecutorNew;
import org.kawanfw.sql.servlet.executor.ServerBatchStatementExecutorNew;
import org.kawanfw.sql.servlet.executor.ServerSqlExecutorCallable;
import org.kawanfw.sql.servlet.executor.ServerSqlExecutorNew;
import org.kawanfw.sql.util.ConnectionParms;
import org.kawanfw.sql.util.SqlAction;
import org.kawanfw.sql.util.SqlActionCallable;
import org.kawanfw.sql.util.SqlActionTransaction;
import org.kawanfw.sql.util.SqlReturnCode;
import org.kawanfw.sql.version.VersionValues;
/**
* @author Nicolas de Pomereu
*
* The method executeRequest() is to to be called from the SqlHttpServer
* Servlet and Class.
* It will execute a client side request with a RemoteConnection
* connection.
*
*/
public class ServerSqlDispatch {
private static boolean DEBUG = FrameworkDebug
.isSet(ServerSqlDispatch.class);
// Errors in SqlHttpServer
private static final String ERR_ACTION_NOT_SET = "ERR_ACTION_NOT_SET";
/**
* Constructor
*/
public ServerSqlDispatch() {
// Does nothing
}
/**
* Execute the client sent sql request
*
* @param request
* the http request
* @param response
* the http response
* @param servletContextTempDir
* The temp dir used by Servlets
* @param commonsConfigurator
* the client commons http configurator specific class
* @param fileConfigurator
* the client file http configurator specific class
* @param sqlConfigurator
* the client sql http configurator specific class
* @param connection
* the Sql Jdbc Connection
* @throws IOException
* if any IOException occurs
*/
public void executeRequest(HttpServletRequest request,
HttpServletResponse response, File servletContextTempDir,
CommonsConfigurator commonsConfigurator,
FileConfigurator fileConfigurator, SqlConfigurator sqlConfigurator)
throws IOException {
// Immediate catch if we are asking a file upload, because parameters
// are
// in unknown sequence. We know it's a upload action if it's mime
// multipart
if (ServletFileUpload.isMultipartContent(request)) {
ServerFileUploadAction serverFileUploadAction = new ServerFileUploadAction();
serverFileUploadAction.executeAction(request, response,
servletContextTempDir, commonsConfigurator,
fileConfigurator);
return;
}
PrintWriter out = null;
try {
debug("executeRequest Start");
// Prepare the response
response.setContentType("text/html");
// Get the send string
debug("ACTION retrieval");
String action = null;
// We must trap the IllegalArgumentException to rethrow properly to
// client
// This happens if there is an encryption problem
try {
action = request.getParameter(Parameter.ACTION);
} catch (IllegalArgumentException e) {
debug("IllegalArgumentException : " + e.toString());
out = response.getWriter();
throw e;
}
String username = request.getParameter(Parameter.USERNAME);
debug("Before if (action.equals(Action.LOGIN_ACTION");
if (action.equals(Action.LOGIN_ACTION)
|| action.equals(Action.BEFORE_LOGIN_ACTION)) {
ServerLoginActionSql serverLoginActionSql = new ServerLoginActionSql();
serverLoginActionSql.executeAction(request, response,
commonsConfigurator, sqlConfigurator, action);
return;
}
debug("ACTION : " + action);
// Redirect to Awake FILE if it's a File request (Blobs/Clobs)
if (isActionForAwakeFile(action)) {
ServerFileDispatch serverFileDispatch = new ServerFileDispatch();
serverFileDispatch.executeRequest(request, response,
servletContextTempDir, commonsConfigurator,
fileConfigurator);
return;
}
debug("After isActionForAwakeFile");
out = response.getWriter();
if (action == null || action.equals("")) {
// out.println(HttpTransferOne.SEND_FAILED + SPACE +
// ERR_ACTION_NOT_SET);
out.println(TransferStatus.SEND_FAILED);
out.println(ERR_ACTION_NOT_SET);
return;
}
debug("Before if (! ServerFileDispatch.isTokenValid(username, token, commonsConfigurator");
String token = request.getParameter(Parameter.TOKEN);
if (!ServerFileDispatch.isTokenValid(username, token,
commonsConfigurator)) {
out.println(TransferStatus.SEND_OK);
out.println(ReturnCode.INVALID_LOGIN_OR_PASSWORD);
return;
}
String connectionId = request
.getParameter(ConnectionParms.CONNECTION_ID);
// If we are in normal mode (not server stateless mode), transaction
// id is > 0
// So Extract a Connection from the pool and store it memory
if (action
.equals(SqlActionTransaction.ACTION_SQL_INIT_REMOTE_CONNECTION)
&& !connectionId.equals("0")) {
// Create the Connection & store it
ConnectionStore connectionStore = new ConnectionStore(username,
connectionId);
Connection connection = commonsConfigurator.getConnection();
connectionStore.put(connection);
debug("ACTION_SQL_INIT_REMOTE_CONNECTION");
debug("username :" + username + ":");
debug("connectionId :" + connectionId + ":");
debug("connection :" + connection + ":");
out.println(TransferStatus.SEND_OK);
return;
}
// If we are not in stateless mode, clean old connections with a
// Thread
if (!connectionId.equals("0") && !ConnectionStoreCleaner.IS_RUNNING) {
ConnectionStoreCleaner cleaner = new ConnectionStoreCleaner(
sqlConfigurator);
cleaner.start();
}
// Notify to Kawan in async mode using a secured Thread that
// the user has successfully logged (done once in JVM session per
// username).
// No notification is done if user.home/.kawansoft/no_notify.txt exists
// or web server name is localhost or 127.0.0.1
if (!KawanNotifier.existsNoNotifyTxt()
&& !KawanNotifier.usernameAlreadyLogged(username)
&& !KawanNotifier.serverNameIsLocalhost()) {
KawanNotifier kawanNotifier = new KawanNotifier(username,
"AceQL_" + VersionValues.VERSION);
kawanNotifier.start();
}
if (action.equals(SqlAction.ACTION_SQL_STATEMENT)) {
executeStatement(request, commonsConfigurator,
fileConfigurator, sqlConfigurator, out);
} else if (action.equals(SqlAction.ACTION_SQL_STATEMENT_BATCH)) {
executeStatementBatch(request, commonsConfigurator,
fileConfigurator, sqlConfigurator, out);
} else if (action.equals(SqlAction.ACTION_SQL_PREP_STATEMENT_BATCH)) {
executePrepStatementBatch(request, commonsConfigurator,
fileConfigurator, sqlConfigurator, out);
} else if (action.equals(SqlAction.ACTION_SQL_GET_METADATA)) {
executeGetMetadata(request, commonsConfigurator,
sqlConfigurator, out);
} else if (action.equals(SqlAction.ACTION_SQL_EXECUTE_RAW)) {
executeRaw(request, commonsConfigurator, fileConfigurator,
sqlConfigurator, out);
} else if (action
.equals(SqlActionTransaction.ACTION_SQL_GET_TRANSACTION_ISOLATION)) {
getTransactionIsolation(request, commonsConfigurator,
sqlConfigurator, out);
} else if (action
.equals(SqlActionCallable.ACTION_SQL_CALLABLE_EXECUTE_RAW)) {
callableExecute(request, commonsConfigurator, fileConfigurator,
sqlConfigurator, out);
} else if (action
.equals(SqlActionCallable.ACTION_SQL_CALLABLE_EXECUTE_QUERY)) {
callableExecuteQuery(request, commonsConfigurator,
fileConfigurator, sqlConfigurator, out);
} else if (action.equals(SqlActionTransaction.ACTION_SQL_COMMIT)
|| action.equals(SqlActionTransaction.ACTION_SQL_ROLLBACK)
|| action.equals(SqlActionTransaction.ACTION_SQL_CON_CLOSE)
) {
setCommitRollbackCloseExecute(request, commonsConfigurator,
sqlConfigurator, out, action);
} else if (action
.equals(SqlActionTransaction.ACTION_SQL_SET_AUTOCOMMIT)
|| action
.equals(SqlActionTransaction.ACTION_SQL_SET_READ_ONLY)
|| action
.equals(SqlActionTransaction.ACTION_SQL_SET_HOLDABILITY)
|| action
.equals(SqlActionTransaction.ACTION_SQL_SET_TRANSACTION_ISOLATION)
) {
setAutocommitReadOnlyHoldabilityTransactionInsolationExecute(
request, commonsConfigurator, out, action);
} else if (action
.equals(SqlActionTransaction.ACTION_SQL_IS_READ_ONLY)
|| action
.equals(SqlActionTransaction.ACTION_SQL_GET_HOLDABILITY)
|| action
.equals(SqlActionTransaction.ACTION_SQL_GET_AUTOCOMMIT)) {
getAutocommitReadOnlyHoldabilityExecute(request,
commonsConfigurator, out, action);
} else if (action
.equals(SqlActionTransaction.ACTION_SQL_SET_SAVEPOINT)
|| action
.equals(SqlActionTransaction.ACTION_SQL_SET_SAVEPOINT_NAME)
|| action
.equals(SqlActionTransaction.ACTION_SQL_SET_ROLLBACK_SAVEPOINT)
|| action
.equals(SqlActionTransaction.ACTION_SQL_SET_RELEASE_SAVEPOINT)) {
setSavepointExecute(request, commonsConfigurator, out, action);
} else if (action.equals(SqlAction.ACTION_SQL_IS_VALID)
|| action.equals(SqlAction.ACTION_SQL_SET_CLIENT_INFO_NAME)
|| action.equals(SqlAction.ACTION_SQL_SET_CLIENT_INFO_PROP)
|| action.equals(SqlAction.ACTION_SQL_GET_CLIENT_INFO_NAME)
|| action.equals(SqlAction.ACTION_SQL_GET_CLIENT_INFO)
|| action.equals(SqlAction.ACTION_SQL_CREATE_ARRAY_OF)) {
connectionInfoExecute(request, commonsConfigurator, out, action);
} else {
throw new IllegalArgumentException("Invalid Sql Action: "
+ action);
}
} catch (Exception e) {
out.println(TransferStatus.SEND_FAILED);
out.println(e.getClass().getName());
out.println(ServerUserThrowable.getMessage(e));
out.println(ExceptionUtils.getStackTrace(e));
try {
ServerLogger.getLogger().log(
Level.WARNING,
Tag.PRODUCT_EXCEPTION_RAISED + " "
+ ServerUserThrowable.getMessage(e));
ServerLogger.getLogger().log(
Level.WARNING,
Tag.PRODUCT_EXCEPTION_RAISED + " "
+ ExceptionUtils.getStackTrace(e));
} catch (Exception e1) {
e1.printStackTrace();
e1.printStackTrace(System.out);
}
}
}
/**
* Returns to client the Connection.getTransactionIsolation() value
*
* @param out
* the servlet print writer
*/
private void getTransactionIsolation(HttpServletRequest request,
CommonsConfigurator commonsConfigurator,
SqlConfigurator sqlConfigurator, PrintWriter out)
throws SQLException {
String connectionId = request
.getParameter(ConnectionParms.CONNECTION_ID);
int transactionIsolation = -1;
if (connectionId.equals("0")) {
// Server Stateless Mode
Connection connection = null;
try {
connection = commonsConfigurator.getConnection();
transactionIsolation = connection.getTransactionIsolation();
} finally {
// Release the connection
ConnectionCloser.freeConnection(connection, sqlConfigurator);
}
} else {
String username = request.getParameter(Parameter.USERNAME);
ConnectionStore connectionStore = new ConnectionStore(username,
connectionId);
Connection connection = connectionStore.get();
if (connection == null) {
out.println(TransferStatus.SEND_OK);
out.println(SqlReturnCode.SESSION_INVALIDATED);
return;
} else {
transactionIsolation = connection.getTransactionIsolation();
}
}
debug("transactionIsolation: " + transactionIsolation);
out.println(TransferStatus.SEND_OK);
out.println("" + transactionIsolation);
}
/**
* Calls a commit(), rollback() or close() on a Connection
*
* @param request
* @param commonsConfigurator
* @param sqlConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentException
*/
private void setCommitRollbackCloseExecute(HttpServletRequest request,
CommonsConfigurator commonsConfigurator,
SqlConfigurator sqlConfigurator, PrintWriter out, String action)
throws IOException, SQLException, IllegalArgumentException {
TransactionUtil.setCommitRollbackCloseExecute(request,
commonsConfigurator, sqlConfigurator, out, action);
}
/**
* Calls a setAutocommit, setReadOnly(), setHoldbility,
* setTransactionIsolation
*
* @param request
* @param commonsConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentException
*/
private void setAutocommitReadOnlyHoldabilityTransactionInsolationExecute(
HttpServletRequest request,
CommonsConfigurator commonsConfigurator, PrintWriter out,
String action) throws IOException, SQLException,
IllegalArgumentException {
TransactionUtil
.setAutocommitReadOnlyHoldabilityTransactionInsolationExecute(
request, commonsConfigurator, out, action);
}
/**
* Calls a getAutocommit(), isReadOnly(), getHoldability(?
*
* @param request
* @param commonsConfigurator
* @param out
* @param action
*/
private void getAutocommitReadOnlyHoldabilityExecute(
HttpServletRequest request,
CommonsConfigurator commonsConfigurator, PrintWriter out,
String action) throws IOException, SQLException,
IllegalArgumentException {
TransactionUtil.getAutocommitReadOnlyHoldabilityExecute(request,
commonsConfigurator, out, action);
}
/**
* Calls a getAutocommit(), isReadOnly(), getHoldability(?
*
* @param request
* @param commonsConfigurator
* @param out
* @param action
*/
private void setSavepointExecute(HttpServletRequest request,
CommonsConfigurator commonsConfigurator, PrintWriter out,
String action) throws IOException, SQLException,
IllegalArgumentException {
SavepointUtil.setSavepointExecute(request, commonsConfigurator, out,
action);
}
private void connectionInfoExecute(HttpServletRequest request,
CommonsConfigurator commonsConfigurator, PrintWriter out,
String action) throws IOException, SQLException,
IllegalArgumentException {
ConnectionInfoUtil.connectionInfoExecute(request, commonsConfigurator,
out, action);
}
/**
* Execute a CallableStatement.executeQuery()
*
* @param request
* @param commonsConfigurator
* @param fileConfigurator
* @param sqlConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentExceptionn
*/
private void callableExecuteQuery(HttpServletRequest request,
CommonsConfigurator commonsConfigurator,
FileConfigurator fileConfigurator, SqlConfigurator sqlConfigurator,
PrintWriter out) throws IOException, SQLException,
IllegalArgumentException {
// Actions that trigger a (Pre)Statement.executeQuery()/executeUppdate()
ServerSqlExecutorCallable serverSqlExecutorCallable = new ServerSqlExecutorCallable(
request, out, commonsConfigurator, fileConfigurator,
sqlConfigurator);
serverSqlExecutorCallable.executeQuery();
}
/**
* Executes a raw CallableStatement.execute()
*
* @param request
* @param commonsConfigurator
* @param fileConfigurator
* @param sqlConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentExceptionn
*/
private void callableExecute(HttpServletRequest request,
CommonsConfigurator commonsConfigurator,
FileConfigurator fileConfigurator, SqlConfigurator sqlConfigurator,
PrintWriter out) throws IOException, SQLException,
IllegalArgumentException {
// Actions that trigger a (Pre)Statement.executeQuery()/executeUppdate()
ServerSqlExecutorCallable serverSqlExecutorCallable = new ServerSqlExecutorCallable(
request, out, commonsConfigurator, fileConfigurator,
sqlConfigurator);
serverSqlExecutorCallable.execute();
}
/**
* Executes a Statement or a PreparedStatement
*
* @param request
* @param commonsConfigurator
* @param fileConfigurator
* @param sqlConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentExceptionn
*/
private void executeStatement(HttpServletRequest request,
CommonsConfigurator commonsConfigurator,
FileConfigurator fileConfigurator, SqlConfigurator sqlConfigurator,
PrintWriter out) throws IOException, SQLException,
IllegalArgumentException {
// Actions that trigger a (Pre)Statement.executeQuery()/executeUppdate()
ServerSqlExecutorNew serverSqlExecutor = new ServerSqlExecutorNew(
request, out, commonsConfigurator, fileConfigurator,
sqlConfigurator);
serverSqlExecutor.executeQueryOrUpdate();
}
/**
* Execute a Statement Batch
*
* @param request
* @param commonsConfigurator
* @param fileConfigurator
* @param sqlConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentException
* @throws SecurityException
*/
private void executeStatementBatch(HttpServletRequest request,
CommonsConfigurator commonsConfigurator,
FileConfigurator fileConfigurator, SqlConfigurator sqlConfigurator,
PrintWriter out) throws IOException, SQLException,
IllegalArgumentException {
// Actions that trigger a Statement batch
ServerBatchStatementExecutorNew serverBatchStatementExecutor = new ServerBatchStatementExecutorNew(
request, out, commonsConfigurator, fileConfigurator,
sqlConfigurator);
serverBatchStatementExecutor.execute();
}
/**
* Execute a PreparedStatement Batch
*
* @param request
* @param commonsConfigurator
* @param fileConfigurator
* @param sqlConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentException
*/
private void executePrepStatementBatch(HttpServletRequest request,
CommonsConfigurator commonsConfigurator,
FileConfigurator fileConfigurator, SqlConfigurator sqlConfigurator,
PrintWriter out) throws IOException, SQLException,
IllegalArgumentException {
// Actions that trigger a PreparedStatement batch
ServerBatchPrepStatementExecutorNew serverBatchPrepStatementExecutor = new ServerBatchPrepStatementExecutorNew(
request, out, commonsConfigurator, fileConfigurator,
sqlConfigurator);
serverBatchPrepStatementExecutor.execute();
}
/**
* Execute a DatabaseMetaData call
*
* @param request
* @param commonsConfigurator
* @param sqlConfigurator
* @param out
* @throws Exception
*/
private void executeGetMetadata(HttpServletRequest request,
CommonsConfigurator commonsConfigurator,
SqlConfigurator sqlConfigurator, PrintWriter out) throws Exception {
// Metadata retrieval
DatabaseMetaDataExecutor databaseMetaDataExecutor = new DatabaseMetaDataExecutor(
request, out, commonsConfigurator, sqlConfigurator);
databaseMetaDataExecutor.execute();
}
/**
* Execute a raw (Prepared)Statement.execute()
*
* @param request
* @param commonsConfigurator
* @param fileConfigurator
* @param sqlConfigurator
* @param out
*/
private void executeRaw(HttpServletRequest request,
CommonsConfigurator commonsConfigurator,
FileConfigurator fileConfigurator, SqlConfigurator sqlConfigurator,
PrintWriter out) throws IOException, SQLException,
IllegalArgumentException {
debug("Before ServerSqlExecutorNew.executeRaw()");
ServerSqlExecutorNew serverSqlExecutor = new ServerSqlExecutorNew(
request, out, commonsConfigurator, fileConfigurator,
sqlConfigurator);
serverSqlExecutor.executeRaw();
debug("After ServerSqlExecutorNew.executeRaw()");
}
/**
* Says if an Action asked by the client is for Awake FILE
*
* @param action
* the action asked by the client side
* @return true if the action is for Awake FILE
*/
private boolean isActionForAwakeFile(String action) {
if (action.startsWith(SqlAction.ACTION_SQL)) {
return false;
} else {
return true;
}
}
/**
* Method called by children Servlet 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);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy