All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src-main.org.awakefw.sql.servlet.DatabaseMetaDataExecutor Maven / Gradle / Ivy

/*
 * This file is part of Awake SQL. 
 * Awake SQL: Remote JDBC access over HTTP.                                    
 * Copyright (C) 2013,  KawanSoft SAS
 * (http://www.kawansoft.com). All rights reserved.                    
 *                                                                         
 * Awake SQL is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.         
 *              
 * Awake 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 General Public License
 * along with this program; if not, see .
 *
 * If you develop commercial activities using Awake SQL, you must: 
 * a) disclose and distribute all source code of your own product,
 * b) license your own product under the GNU General Public License.
 * 
 * You can be released from the requirements of the license by
 * purchasing a commercial license. Buying such a license will allow you 
 * to ship Awake SQL with your closed source products without disclosing 
 * the source code.
 *
 * For more information, please contact KawanSoft SAS at this
 * address: [email protected]
 * 
 * Any modifications to this file must keep this entire header
 * intact.
 */
package org.awakefw.sql.servlet;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.awakefw.commons.api.server.AwakeCommonsConfigurator;
import org.awakefw.file.api.util.AwakeDebug;
import org.awakefw.file.api.util.HtmlConverter;
import org.awakefw.file.json.ListOfStringTransport;
import org.awakefw.file.util.AwakeClientLogger;
import org.awakefw.file.util.JavaValueBuilder;
import org.awakefw.file.util.Tag;
import org.awakefw.file.util.TransferStatus;
import org.awakefw.file.util.parms.Parameter;
import org.awakefw.sql.api.server.AwakeSqlConfigurator;
import org.awakefw.sql.json.no_obfuscation.DatabaseMetaDataHolder;
import org.awakefw.sql.json.no_obfuscation.DatabaseMetaDataHolderTransport;
import org.awakefw.sql.servlet.connection.ConnectionStore;
import org.awakefw.sql.servlet.sql.ResultSetMetaDataWriter;
import org.awakefw.sql.servlet.sql.ResultSetWriter;
import org.awakefw.sql.servlet.sql.ServerStatement;
import org.awakefw.sql.util.ConnectionParms;
import org.awakefw.sql.util.SqlReturnCode;

/**
 * Execute MetaData requests.
 * 
 * @author Nicolas de Pomereu
 * 
 */
public class DatabaseMetaDataExecutor {
    private static boolean DEBUG = AwakeDebug
	    .isSet(DatabaseMetaDataExecutor.class);
    public static String CR_LF = System.getProperty("line.separator");

    private HttpServletRequest request = null;
    private PrintWriter out = null;

    private AwakeCommonsConfigurator awakeCommonsConfigurator = null;
    private AwakeSqlConfigurator awakeSqlConfigurator = null;

    /**
     * Constructor
     * 
     * @param request
     *            the servlet http request
     * @param out
     *            the servlet output stream
     * @param awakeCommonsConfigurator
     *            the Awake Commons Configurator
     * @param awakeSqlConfigurator
     *            the Awake SQL Configurator
     */
    public DatabaseMetaDataExecutor(HttpServletRequest request,
	    PrintWriter out, AwakeCommonsConfigurator awakeCommonsConfigurator,
	    AwakeSqlConfigurator awakeSqlConfigurator)

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

	this.awakeCommonsConfigurator = awakeCommonsConfigurator;
	this.awakeSqlConfigurator = awakeSqlConfigurator;

    }

    /**
     * Execute the MetaData request
     */
    public void execute() throws Exception {
	// String action = request.getParameter(SqlAction.ACTION) ;

	String username = request.getParameter(Parameter.USERNAME);
	String methodName = request.getParameter(Parameter.METHOD_NAME);
	String connectionId = request
		.getParameter(ConnectionParms.CONNECTION_ID);

	// methodName = HtmlConverter.fromHtml(methodName);

	debug("Parameter.METHOD_NAME: " + methodName);

	Connection connection = null;

	if (connectionId.equals("0")) {
	    try {
		connection = awakeCommonsConfigurator.getConnection();

		boolean isAllowed = AwakeSqlConfiguratorCall.allowGetMetaData(
			awakeSqlConfigurator, username, connection);

		if (!isAllowed) {
		    String message = Tag.AWAKE_SECURITY
			    + "Database Catalog Query not authorized.";
		    throw new SecurityException(message);
		}

		DatabaseMetaData databaseMetaData = connection.getMetaData();

		// If methodName is getMetaData ==> just return the
		// DatabaseMetaData
		if (methodName.equals("getMetaData")) {
		    DatabaseMetaDataHolder databaseMetaDataHolder = new DatabaseMetaDataHolder();
		    databaseMetaDataHolder
			    .setDatabaseMetaDataHolder(databaseMetaData);

		    String jsonString = DatabaseMetaDataHolderTransport
			    .toJson(databaseMetaDataHolder);
		    jsonString = HtmlConverter.toHtml(jsonString);
		    out.println(TransferStatus.SEND_OK);
		    out.println(jsonString);
		    return;
		} else if (methodName.equals("getCatalog")) {
		    String catalog = connection.getCatalog();
		    catalog = HtmlConverter.toHtml(catalog);
		    out.println(TransferStatus.SEND_OK);
		    out.println(catalog);
		} else {
		    // Call the DatabaseMetaData.method with reflection:
		    callMetaDataFunction(request, out, connection);
		}
	    } finally {
		// Release the connection
		ConnectionCloser.freeConnection(connection,
			awakeSqlConfigurator);
	    }
	} else {
	    ConnectionStore connectionStore = new ConnectionStore(username,
		    connectionId);
	    connection = connectionStore.get();

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

	    boolean isAllowed = AwakeSqlConfiguratorCall.allowGetMetaData(
		    awakeSqlConfigurator, username, connection);

	    if (!isAllowed) {
		String message = Tag.AWAKE_SECURITY
			+ "Database Catalog Query not authorized.";
		throw new SecurityException(message);
	    }

	    DatabaseMetaData databaseMetaData = connection.getMetaData();

	    // If methodName is getMetaData ==> just return the
	    // DatabaseMetaData
	    if (methodName.equals("getMetaData")) {
		DatabaseMetaDataHolder databaseMetaDataHolder = new DatabaseMetaDataHolder();
		databaseMetaDataHolder
			.setDatabaseMetaDataHolder(databaseMetaData);

		String jsonString = DatabaseMetaDataHolderTransport
			.toJson(databaseMetaDataHolder);
		jsonString = HtmlConverter.toHtml(jsonString);
		out.println(TransferStatus.SEND_OK);
		out.println(jsonString);
		return;
	    } else if (methodName.equals("getCatalog")) {
		String catalog = connection.getCatalog();
		catalog = HtmlConverter.toHtml(catalog);
		out.println(TransferStatus.SEND_OK);
		out.println(catalog);
	    } else {
		// Call the DatabaseMetaData.method with reflection:
		callMetaDataFunction(request, out, connection);
	    }
	}

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

    }

    /**
     * 
     * Calls a remote method from the PC 
* Please note that all invocation are trapped and routed as code string to * the PC. * * @param request * the http request * @param awakeCommonsConfigurator * the commons configurator defined by the user * @param awakeFileConfigurator * the file configurator defined by the user * @param out * the servlet output stream * @param username * the client login (for security check) * * * @throws IOException * all Awake, network, etc. errors * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException * @throws NoSuchMethodException * @throws SecurityException * @throws InvocationTargetException * @throws IllegalArgumentException */ private void callMetaDataFunction(HttpServletRequest request, PrintWriter out, Connection connection) throws SQLException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException { // The method name String methodName = request.getParameter(Parameter.METHOD_NAME); // methodName = HtmlConverter.fromHtml(methodName); // The parms name String paramsTypes = request.getParameter(Parameter.PARAMS_TYPES); String paramsValues = request.getParameter(Parameter.PARAMS_VALUES); // Make sure all values are not null and trimed methodName = this.getTrimValue(methodName); paramsTypes = this.getTrimValue(paramsTypes); paramsValues = this.getTrimValue(paramsValues); debug("actionInvokeRemoteMethod:methodName : " + methodName); // paramsTypes = HtmlConverter.fromHtml(paramsTypes); // paramsValues = HtmlConverter.fromHtml(paramsValues); List listParamsTypes = ListOfStringTransport .fromJson(paramsTypes); List listParamsValues = ListOfStringTransport .fromJson(paramsValues); debug("actionInvokeRemoteMethod:listParamsTypes : " + listParamsTypes); debug("actionInvokeRemoteMethod:listParamsValues : " + listParamsValues); DatabaseMetaData databaseMetaData = connection.getMetaData(); // Trap DatabaseMetaData.getTables() & DatabaseMetaData.getUDTs() // that have special array String[] or int[] parameters if (methodName.equals("getTables") || methodName.equals("getUDTs") || methodName.equals("getPrimaryKeys")) { DatabaseMetaDataSpecial databaseMetaDataSpecial = new DatabaseMetaDataSpecial( databaseMetaData, methodName, listParamsValues); ResultSet rs = databaseMetaDataSpecial.execute(); dumpResultSetOnServletOutStream(rs); return; } @SuppressWarnings("rawtypes") Class[] argTypes = new Class[listParamsTypes.size()]; Object[] values = new Object[listParamsValues.size()]; for (int i = 0; i < listParamsTypes.size(); i++) { String value = listParamsValues.get(i); String javaType = listParamsTypes.get(i); JavaValueBuilder javaValueBuilder = new JavaValueBuilder(javaType, value); argTypes[i] = javaValueBuilder.getClassOfValue(); values[i] = javaValueBuilder.getValue(); // Trap NULL values if (values[i].equals("NULL")) { values[i] = null; } debug("argTypes[i]: " + argTypes[i]); debug("values[i] : " + values[i]); } Class c = Class.forName("java.sql.DatabaseMetaData"); Object theObject = databaseMetaData; // Invoke the method Method main = null; Object resultObj = null; // Get the Drvier Info String database = ""; String productVersion = ""; String DriverName = ""; String DriverVersion = ""; String driverInfo = Tag.AWAKE; // try { // database = databaseMetaData.getDatabaseProductName(); // productVersion = databaseMetaData.getDatabaseProductVersion(); // DriverName = databaseMetaData.getDriverName(); // DriverVersion= databaseMetaData.getDriverVersion(); // driverInfo += database + " " + productVersion + " " + DriverName + // " " + DriverVersion; // } catch (Exception e1) { // AwakeLogger.log(Tag.AWAKE + "Impossible to get User Driver info."); // } database = databaseMetaData.getDatabaseProductName(); productVersion = databaseMetaData.getDatabaseProductVersion(); DriverName = databaseMetaData.getDriverName(); DriverVersion = databaseMetaData.getDriverVersion(); driverInfo += database + " " + productVersion + " " + DriverName + " " + DriverVersion; String methodParams = getMethodParams(values); try { main = c.getDeclaredMethod(methodName, argTypes); } catch (SecurityException e) { throw new SecurityException( driverInfo + " - Security - Impossible to get declared DatabaseMetaData." + methodName + "(" + methodParams + ")"); } catch (NoSuchMethodException e) { throw new NoSuchMethodException( driverInfo + " - No Such Method - Impossible get declared DatabaseMetaData." + methodName + "(" + methodParams + ")"); } try { resultObj = main.invoke(theObject, values); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(driverInfo + " - Impossible to call DatabaseMetaData." + methodName + "(" + methodParams + ")"); } catch (IllegalAccessException e) { throw new IllegalAccessException(driverInfo + " - Impossible to access DatabaseMetaData method." + methodName + "(" + methodParams + ")"); } catch (InvocationTargetException e) { throw new InvocationTargetException(e, driverInfo + " - Impossible to invoke DatabaseMetaData method." + methodName + "(" + methodParams + ")"); } if (resultObj instanceof ResultSet) { ResultSet rs = (ResultSet) resultObj; dumpResultSetOnServletOutStream(rs); } else { // All other formats are handled in String String result = null; if (resultObj != null) result = resultObj.toString(); debug("actionInvokeRemoteMethod:result: " + result); result = HtmlConverter.toHtml(result); out.println(TransferStatus.SEND_OK); out.println(result); } } /** * Returns the method parameters as (value1, value2, ...) * * @param values * the value array * @return the method parameters as (value1, value2, ...) */ private String getMethodParams(Object[] values) { if (values.length == 0) { return ""; } String returnValue = "("; for (int i = 0; i < values.length; i++) { returnValue += values[i]; if (i < values.length - 1) { returnValue += ", "; } } returnValue += ")"; return returnValue; } /** * Dump the result set, releasing it as soon as possible, on the output * stream * * @param rs * the resut set to dump * * @throws SQLException * @throws IOException * @throws SecurityException */ public void dumpResultSetOnServletOutStream(ResultSet rs) throws SQLException, IOException { BufferedWriter br = null; File tempFileForResultSet = null; try { tempFileForResultSet = ServerStatement.createTempFileForResultSet(); br = new BufferedWriter(new FileWriter(tempFileForResultSet)); br.write(TransferStatus.SEND_OK + CR_LF); ResultSetMetaData meta = rs.getMetaData(); ResultSetWriter resultSetWriter = new ResultSetWriter(request, br, awakeCommonsConfigurator, null, awakeSqlConfigurator, "ResultSetMetaData", "ResultSetMetaData", null); resultSetWriter.write(rs); // Write the separator between ResultSet & ResultSet.getMetaData() br.write("ResultSet.getMetaData()" + CR_LF); // Write also the associated ResultSet.getMetaData(); ResultSetMetaDataWriter resultSetMetaDataWriter = new ResultSetMetaDataWriter( br, null, awakeCommonsConfigurator, awakeSqlConfigurator); resultSetMetaDataWriter.write(meta); IOUtils.closeQuietly(br); dumpFileOnServletOutStream(tempFileForResultSet); } finally { if (rs != null) { rs.close(); } IOUtils.closeQuietly(br); tempFileForResultSet.delete(); } } /** * return a "" empty string if null or a trimed stgring if not null * * @param action * the input string * @return the empty stgring or trimed string */ private String getTrimValue(String string) { if (string == null) { return ""; } else { return string.trim(); } } /** * Dump the file with the result set on the servlet output stream * * @param tempFilesForResultSet * @throws FileNotFoundException * @throws IOException */ private void dumpFileOnServletOutStream(File tempFileForResultSet) throws FileNotFoundException, IOException { BufferedReader br = new BufferedReader(new FileReader( tempFileForResultSet)); try { IOUtils.copy(br, out); } finally { IOUtils.closeQuietly(br); } } /** * Method called by children Servlest for debug purpose Println is done only * if class name name is in awake-debug.ini */ public static void debug(String s) { if (DEBUG) { AwakeClientLogger.log(s); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy