
src-main.org.awakefw.sql.servlet.ServerAwakeSqlDispatch Maven / Gradle / Ivy
/*
* Awake File: Easy file upload & download through HTTP with Java
* Awake SQL: Remote JDBC access through HTTP.
* Copyright (C) 2012, Kawan Softwares S.A.S.
* (http://www.awakeframework.org). All rights reserved.
*
* Awake File/SQL 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.
*
* Awake File/SQL 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.
*/
//SqlHttpServerDispatch
//Copyright (c) Kawan Softwares S.A.S, 2012
//
//Last Updates:
// 3 d?c. 2009 17:33:16 Nicolas de Pomereu
// 15/12/09 14:35 NDP - comments
// 14/01/10 18:05 NDP - Add getSynchronizedMode()/setSynchronizedMode() per user
// 25/01/10 19:30 NDP - If the file sql operation is now allowed, return false when login
// 17/02/10 17:25 NDP - No more connection.set/setHoldability anymore: not always supported
// 23/02/10 21:10 NDP - ServerAwakeSqlDispatch: Add Connectikon parameters to checkLoginDiscardStatus()
// 23/03/10 12:00 NDP - ServerAwakeSqlDispatch: Send back an ok if sqlOrdersAndParmsStoreList is empty
// 04/10/10 20:50 NDP - ServerAwakeSqlDispatch: executeAfterDiscard was missing the ip address parameter
// 12/10/10 17:50 NDP : ServerAwakeSqlDispatch: all actions on files are dispatched with an AwakeFileActionManager
// 18/11/10 11:30 NDP : ServerAwakeSqlDispatch: Comments
// 12/04/12 17:05 NDP : ServerAwakeSqlDispatch: print class name, message & stack trace on servlet output stream
// 04/06/11 12:10 NDP - ServerAwakeSqlDispatch: rename login to username
// 08/06/11 10:45 NDP : ServerAwakeSqlDispatch: set debug to false;
// 19/07/11 18:55 NDP : ServerAwakeSqlDispatch: set debug to false;
// 26/09/11 18:05 NDP : ServerAwakeSqlDispatch: add SqlAction.ACTION_SQL_GET_METADATA management
// 29/09/11 14:45 NDP : ServerAwakeSqlDispatch: Suppress old commented methods with state full session
// 30/09/11 15:20 NDP : ServerAwakeSqlDispatch: use Parameter.ACTION instead of suppressed SqlAction.ACTION
// 19/10/11 12:20 NDP - ServerAwakeSqlDispatch: add ACTION_SQL_PREP_STATEMENT_BATCH
// 16/11/11 12:50 NDP - ServerAwakeSqlDispatch: use unique method per switch on SqlAction
// 19/11/11 17:40 NDP - ServerAwakeSqlDispatch: correctly reinit the Connection before release in the pool
// 21/11/11 17:00 NDP - ServerAwakeSqlDispatch: put out = response.getWriter() at top (after try)
// 22/11/11 17:25 NDP : ServerAwakeSqlDispatch: throw Exception on first getParameter(): means encryption fails
// 08/12/11 20:30 NDP : ServerAwakeSqlDispatch: no more fromHtml conversion (comments)
// 13/12/11 12:20 NDP : ServerAwakeSqlDispatch: add getTransactionIsolation()
// 19/12/11 21:05 NDP : ServerAwakeSqlDispatch: use InitConnectionPool class for re-init of connections properties
// 16/02/12 15:50 NDP : ServerAwakeSqlDispatch: use AwakeCommonsConfigurator.computeAuthToken()
// 24/03/12 18:35 NDP : ServerAwakeSqlDispatch: use new ConnectionDefaultsStore
// 29/03/12 20:05 NDP : ServerAwakeSqlDispatch: call ConnectionDefaultsStore anyway
// (more secure if dynamic database change)
// 02/04/12 16:20 NDP : ServerAwakeSqlDispatch: add Tag.AWAKE_USER_CONFIG_FAIL to exception.getMessage()
// thrown back to client if exception is thrown by a Configurator
package org.awakefw.sql.servlet;
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.awakefw.commons.api.server.AwakeCommonsConfigurator;
import org.awakefw.file.api.server.AwakeFileConfigurator;
import org.awakefw.file.api.server.fileaction.AwakeFileActionManager;
import org.awakefw.file.api.util.AwakeDebug;
import org.awakefw.file.http.HttpTransfer;
import org.awakefw.file.http.HttpTransferOne;
import org.awakefw.file.servlet.ServerAwakeFileDispatch;
import org.awakefw.file.servlet.ServerFileUploadAction;
import org.awakefw.file.servlet.ServerLoginAction;
import org.awakefw.file.servlet.ServerUserException;
import org.awakefw.file.util.AwakeLogger;
import org.awakefw.file.util.Tag;
import org.awakefw.file.util.parms.Action;
import org.awakefw.file.util.parms.Parameter;
import org.awakefw.file.util.parms.ReturnCode;
import org.awakefw.sql.api.server.AwakeSqlConfigurator;
import org.awakefw.sql.util.ConnectionDefaultsStore;
import org.awakefw.sql.util.SqlAction;
/**
* @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 HttpConnection
* connection.
*
*/
public class ServerAwakeSqlDispatch {
private static boolean DEBUG = AwakeDebug
.isSet(ServerAwakeSqlDispatch.class);
// Errors in SqlHttpServer
private static final String ERR_ACTION_NOT_SET = "ERR_ACTION_NOT_SET";
/**
* Constructor
*/
public ServerAwakeSqlDispatch() {
// Does nothing
}
/**
* Execute the client sent sql request
*
* @param request
* the http request
* @param response
* the http response
* @param awakeCommonsConfigurator
* the client commons http configurator specific class
* @param awakeFileConfigurator
* the client file http configurator specific class
* @param awakeSqlConfigurator
* the client sql http configurator specific class
* @param awakeFileActionManager
* the file action manager
* @param connection
* the Sql Jdbc Connection
* @throws IOException
* if any IOException occurs
*/
public void executeRequest(HttpServletRequest request,
HttpServletResponse response,
AwakeCommonsConfigurator awakeCommonsConfigurator,
AwakeFileConfigurator awakeFileConfigurator,
AwakeSqlConfigurator awakeSqlConfigurator,
AwakeFileActionManager awakeFileActionManager) 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 dispatchAction = new ServerFileUploadAction();
dispatchAction.executeAction(request, response,
awakeCommonsConfigurator, awakeFileConfigurator,
awakeFileActionManager);
return;
}
PrintWriter out = null;
try {
debug("executeRequest Start");
// Prepare the response
response.setContentType("text/html");
// Fist thing to do: Stores in static memory the user settings for this transaction
// This method will also test the Connection is created, otw a
// detailed Exception is thrown
debug("Before new ConnectionDefaultsStore.");
try {
ConnectionDefaultsStore connectionDefaultsStore = new ConnectionDefaultsStore(
awakeCommonsConfigurator);
connectionDefaultsStore.init();
} catch (Exception e) {
out = response.getWriter();
throw e;
}
debug("After new ConnectionDefaultsStore.");
// 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;
}
debug("ACTION : " + action);
// Redirect to Awake File if it's a File request (Blobs/Clobs)
if (isActionForAwakeFile(action)) {
ServerAwakeFileDispatch dispatch = new ServerAwakeFileDispatch();
dispatch.executeRequest(request, response,
awakeCommonsConfigurator, awakeFileConfigurator,
awakeFileActionManager);
return;
}
debug("After isActionForAwakeFile");
out = response.getWriter();
String username = request.getParameter(Parameter.LOGIN);
String token = request.getParameter(Parameter.TOKEN);
if (action == null || action.equals("")) {
// out.println(HttpTransferOne.SEND_FAILED + SPACE +
// ERR_ACTION_NOT_SET);
out.println(HttpTransferOne.SEND_FAILED);
out.println(ERR_ACTION_NOT_SET);
return;
}
debug("Before if (action.equals(Action.LOGIN_ACTION");
// Special action for Login, because Token does not exists and must
// be built
if (action.equals(Action.LOGIN_ACTION)
|| action.equals(Action.BEFORE_LOGIN_ACTION)) {
ServerLoginAction dispatchAction = new ServerLoginAction();
dispatchAction.executeAction(request, response,
awakeCommonsConfigurator, action);
return;
}
debug("Before if (! ServerAwakeFileDispatch.isTokenValid(username, token, awakeCommonsConfigurator");
if (! ServerAwakeFileDispatch.isTokenValid(username, token, awakeCommonsConfigurator))
{
out.println(HttpTransfer.SEND_OK);
out.println(ReturnCode.INVALID_LOGIN_OR_PASSWORD);
return;
}
debug("Before if (action.equals(SqlAction.ACTION_SQL_STATEMENT)) {");
if (action.equals(SqlAction.ACTION_SQL_STATEMENT)) {
executeStatement(request, awakeCommonsConfigurator,
awakeFileConfigurator, awakeSqlConfigurator, out);
} else if (action.equals(SqlAction.ACTION_SQL_STATEMENT_BATCH)) {
executeStatementBatch(request, awakeCommonsConfigurator,
awakeFileConfigurator, awakeSqlConfigurator, out);
} else if (action.equals(SqlAction.ACTION_SQL_PREP_STATEMENT_BATCH)) {
executePrepStatementBatch(request, awakeCommonsConfigurator,
awakeFileConfigurator, awakeSqlConfigurator, out);
} else if (action.equals(SqlAction.ACTION_SQL_GET_METADATA)) {
executeGetMetadata(request, awakeCommonsConfigurator,
awakeSqlConfigurator, out);
} else if (action.equals(SqlAction.ACTION_SQL_EXECUTE_RAW)) {
executeRaw(request, awakeCommonsConfigurator,
awakeFileConfigurator, awakeSqlConfigurator, out);
} else if (action
.equals(SqlAction.ACTION_SQL_GET_TRANSACTION_ISOLATION)) {
getTransactionIsolation(awakeCommonsConfigurator, out);
} else {
throw new IllegalArgumentException("Invalid Sql Action: "
+ action);
}
} catch (Exception e) {
out.println(HttpTransfer.SEND_FAILED);
out.println(e.getClass().getName());
out.println(ServerUserException.getMessage(e));
out.println(ExceptionUtils.getStackTrace(e));
try {
AwakeLogger.log(Level.WARNING, Tag.AWAKE_EXCEPTION_RAISED
+ ServerUserException.getMessage(e));
AwakeLogger.log(Level.WARNING, Tag.AWAKE_EXCEPTION_RAISED
+ ExceptionUtils.getStackTrace(e));
} catch (Exception e1) {
e1.printStackTrace();
e1.printStackTrace(System.out);
}
}
}
/**
* Returns to client the Connection.getTransactionIsolation() value
*
* @param awakeCommonsConfigurator
* The commons configurator
* @param out
* the servlet print writer
*/
private void getTransactionIsolation(
AwakeCommonsConfigurator awakeCommonsConfigurator, PrintWriter out)
throws SQLException {
Connection connection = null;
int transactionIsolation = -1;
try {
connection = awakeCommonsConfigurator.getConnection();
transactionIsolation = connection.getTransactionIsolation();
} finally {
// Release the connection
ServerAwakeSqlDispatch.cleanAndFreeConnection(connection,
awakeCommonsConfigurator);
}
debug("transactionIsolation: " + transactionIsolation);
out.println(HttpTransferOne.SEND_OK);
out.println("" + transactionIsolation);
}
/**
* Execute a Statement or a PreparedStatement
*
* @param request
* @param awakeCommonsConfigurator
* @param awakeFileConfigurator
* @param awakeSqlConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentExceptionn
*/
private void executeStatement(HttpServletRequest request,
AwakeCommonsConfigurator awakeCommonsConfigurator,
AwakeFileConfigurator awakeFileConfigurator,
AwakeSqlConfigurator awakeSqlConfigurator, PrintWriter out)
throws IOException, SQLException, IllegalArgumentException {
// Actions that trigger a (Pre)Statement.executeQuery()/executeUppdate()
ServerSqlExecutor serverSqlExecutor = new ServerSqlExecutor(request,
out, awakeCommonsConfigurator, awakeFileConfigurator,
awakeSqlConfigurator);
serverSqlExecutor.executeQueryOrUpdate();
}
/**
* Execute a Statement Batch
*
* @param request
* @param awakeCommonsConfigurator
* @param awakeFileConfigurator
* @param awakeSqlConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentException
* @throws SecurityException
*/
private void executeStatementBatch(HttpServletRequest request,
AwakeCommonsConfigurator awakeCommonsConfigurator,
AwakeFileConfigurator awakeFileConfigurator,
AwakeSqlConfigurator awakeSqlConfigurator, PrintWriter out)
throws IOException, SQLException, IllegalArgumentException {
// Actions that trigger a Statement batch
ServerBatchStatementExecutor serverBatchStatementExecutor = new ServerBatchStatementExecutor(
request, out, awakeCommonsConfigurator, awakeFileConfigurator,
awakeSqlConfigurator);
serverBatchStatementExecutor.execute();
}
/**
* Execute a PreparedStatement Batch
*
* @param request
* @param awakeCommonsConfigurator
* @param awakeFileConfigurator
* @param awakeSqlConfigurator
* @param out
* @throws IOException
* @throws SQLException
* @throws IllegalArgumentException
*/
private void executePrepStatementBatch(HttpServletRequest request,
AwakeCommonsConfigurator awakeCommonsConfigurator,
AwakeFileConfigurator awakeFileConfigurator,
AwakeSqlConfigurator awakeSqlConfigurator, PrintWriter out)
throws IOException, SQLException, IllegalArgumentException {
// Actions that trigger a PreparedStatement batch
ServerBatchPrepStatementExecutor serverBatchPrepStatementExecutor = new ServerBatchPrepStatementExecutor(
request, out, awakeCommonsConfigurator, awakeFileConfigurator,
awakeSqlConfigurator);
serverBatchPrepStatementExecutor.execute();
}
/**
* Execute a DatabaseMetaData call
*
* @param request
* @param awakeCommonsConfigurator
* @param awakeSqlConfigurator
* @param out
* @throws Exception
*/
private void executeGetMetadata(HttpServletRequest request,
AwakeCommonsConfigurator awakeCommonsConfigurator,
AwakeSqlConfigurator awakeSqlConfigurator, PrintWriter out)
throws Exception {
// Metadata retrieval
DatabaseMetaDataExecutor databaseMetaDataExecutor = new DatabaseMetaDataExecutor(
request, out, awakeCommonsConfigurator, awakeSqlConfigurator);
databaseMetaDataExecutor.execute();
}
/**
* Execute a raw (Prepared)Statement.execute()
*
* @param request
* @param awakeCommonsConfigurator
* @param awakeFileConfigurator
* @param awakeSqlConfigurator
* @param out
*/
private void executeRaw(HttpServletRequest request,
AwakeCommonsConfigurator awakeCommonsConfigurator,
AwakeFileConfigurator awakeFileConfigurator,
AwakeSqlConfigurator awakeSqlConfigurator, PrintWriter out)
throws IOException, SQLException, IllegalArgumentException {
ServerSqlExecutor serverSqlExecutor = new ServerSqlExecutor(request,
out, awakeCommonsConfigurator, awakeFileConfigurator,
awakeSqlConfigurator);
serverSqlExecutor.executeRaw();
}
/**
* Clean the connection (aka put in write/read & DEFAULT_ISOLATION_LEVEL)
* and then release it
*
* @param connection
* @param awakeCommonsConfigurator
*/
public static void cleanAndFreeConnection(Connection connection,
AwakeCommonsConfigurator awakeCommonsConfigurator) {
// Reset the transaction to it's back state before realeasing it
try {
if (connection != null) {
connection.setAutoCommit(true);
connection.setReadOnly(false);
ConnectionDefaultsStore connectionDefaultsStore = new ConnectionDefaultsStore(
awakeCommonsConfigurator);
connection.setTransactionIsolation(connectionDefaultsStore
.getTransactionIsolation());
connection.setHoldability(connectionDefaultsStore
.getHoldability());
// Release the Connection into the pool
connection.close();
}
} catch (SQLException e) {
AwakeLogger.log(Level.WARNING, ExceptionUtils.getStackTrace(e));
}
}
/**
* 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 debug_list.ini
*/
public static void debug(String s) {
if (DEBUG) {
AwakeLogger.log(s);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy