org.kawanfw.sql.servlet.ServerSqlManager.java Source code

Java tutorial

Introduction

Here is the source code for org.kawanfw.sql.servlet.ServerSqlManager.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;

import static org.kawanfw.file.servlet.ServerFileManager.COMMONS_CONFIGURATOR_CLASS_NAME;
import static org.kawanfw.file.servlet.ServerFileManager.FILE_CONFIGURATOR_CLASS_NAME;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.kawanfw.commons.api.server.CommonsConfigurator;
import org.kawanfw.commons.api.server.DefaultCommonsConfigurator;
import org.kawanfw.commons.server.util.ServerLogger;
import org.kawanfw.commons.server.util.embed.TomcatModeStore;
import org.kawanfw.commons.util.FrameworkDebug;
import org.kawanfw.commons.util.Tag;
import org.kawanfw.commons.util.TransferStatus;
import org.kawanfw.file.api.server.DefaultFileConfigurator;
import org.kawanfw.file.api.server.FileConfigurator;
import org.kawanfw.file.servlet.RequestInfoStore;
import org.kawanfw.file.servlet.ServerFileManager;
import org.kawanfw.file.servlet.convert.HttpServletRequestConvertor;
import org.kawanfw.sql.api.server.DefaultSqlConfigurator;
import org.kawanfw.sql.api.server.SqlConfigurationException;
import org.kawanfw.sql.api.server.SqlConfigurator;
import org.kawanfw.sql.tomcat.ServletParametersStore;
import org.kawanfw.sql.tomcat.TomcatStarterUtil;
import org.kawanfw.sql.util.SqlTag;
import org.kawanfw.sql.version.Version;

/**
 * Http JDBC Server
 * 
 * @author Nicolas de Pomereu
 */

@SuppressWarnings("serial")
public class ServerSqlManager extends HttpServlet {

    private static boolean DEBUG = FrameworkDebug.isSet(ServerSqlManager.class);

    public static String CR_LF = System.getProperty("line.separator");

    public static final String SQL_CONFIGURATOR_CLASS_NAME = "sqlConfiguratorClassName";

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

    /** Says that the ServerLogger is ok and we can log the exceptions */
    private boolean serverLoggerOk = false;

    /** The Exception thrown at init */
    private Exception exception = null;

    /** The init error message trapped */
    private String initErrrorMesage = null;

    /** Required to pass license parameters at doPost() */
    private Properties properties;

    /**
     * Init
     */

    public void init(ServletConfig config) throws ServletException {
        super.init(config);

        // Variable use to store the current name when loading, used to
        // detail
        // the exception in the catch clauses
        String classNameToLoad = null;

        String commonsConfiguratorClassName;
        String fileConfiguratorClassName;
        String sqlConfiguratorClassName;

        String servletName = this.getServletName();

        String index = null;

        if (!TomcatModeStore.isTomcatEmbedded()) {
            System.out.println(SqlTag.SQL_PRODUCT_START + " " + Version.getServerVersion());
        }

        // We are in SQL Framework
        TomcatModeStore.setFrameworkSql(true);

        try {

            if (!TomcatModeStore.isTomcatEmbedded()) {
                String propertiesFileStr = config.getInitParameter("properties");

                if (propertiesFileStr == null || propertiesFileStr.isEmpty()) {

                    String aceqlHome = System.getenv("ACEQL_HOME");

                    if (aceqlHome != null) {

                        // Remove surrounding " if present
                        aceqlHome = aceqlHome.replaceAll("\"", "");

                        if (aceqlHome.endsWith(File.separator)) {
                            aceqlHome = StringUtils.substringBeforeLast(aceqlHome, File.separator);
                        }
                        propertiesFileStr = aceqlHome + File.separator + "conf" + File.separator
                                + "aceql-server.properties";
                    } else {
                        throw new SqlConfigurationException(Tag.PRODUCT_USER_CONFIG_FAIL
                                + " ACEQL_HOME property not set. Impossible to use the default ACEQL_HOME"
                                + File.separator + "conf" + File.separator + "aceql-server.properties file");
                    }

                    //          throw new SqlConfigurationException(
                    //             Tag.PRODUCT_USER_CONFIG_FAIL
                    //                + " <param-name> \"properties\" not found for servlet "
                    //                + servletName);
                }

                File propertiesFile = new File(propertiesFileStr);

                if (!propertiesFile.exists()) {
                    throw new SqlConfigurationException(
                            Tag.PRODUCT_USER_CONFIG_FAIL + " properties file not found: " + propertiesFile);
                }

                System.out.println(SqlTag.SQL_PRODUCT_START + " " + "Using properties file: " + propertiesFile);

                properties = TomcatStarterUtil.getProperties(propertiesFile);

                index = TomcatStarterUtil.getIndexFromServletName(properties, servletName);

                TomcatStarterUtil.setInitParametersInStore(properties, index);

                // Create the default DataSource if necessary
                TomcatStarterUtil.createAndStoreDataSource(properties, index);
            }

            commonsConfiguratorClassName = ServletParametersStore.getInitParameter(servletName,
                    COMMONS_CONFIGURATOR_CLASS_NAME);
            fileConfiguratorClassName = ServletParametersStore.getInitParameter(servletName,
                    FILE_CONFIGURATOR_CLASS_NAME);
            sqlConfiguratorClassName = ServletParametersStore.getInitParameter(servletName,
                    SQL_CONFIGURATOR_CLASS_NAME);

            debug("commonsConfiguratorClassName: " + commonsConfiguratorClassName);
            debug("fileConfiguratorClassName   : " + fileConfiguratorClassName);
            debug("sqlConfiguratorClassName    : " + sqlConfiguratorClassName);

            // Check spelling with first letter capitalized

            if (commonsConfiguratorClassName == null || commonsConfiguratorClassName.isEmpty()) {
                String capitalized = StringUtils.capitalize(ServerFileManager.COMMONS_CONFIGURATOR_CLASS_NAME);
                commonsConfiguratorClassName = ServletParametersStore.getInitParameter(servletName, capitalized);
            }

            if (fileConfiguratorClassName == null || fileConfiguratorClassName.isEmpty()) {
                String capitalized = StringUtils.capitalize(ServerFileManager.FILE_CONFIGURATOR_CLASS_NAME);
                fileConfiguratorClassName = ServletParametersStore.getInitParameter(servletName, capitalized);
            }

            if (sqlConfiguratorClassName == null || sqlConfiguratorClassName.isEmpty()) {
                String capitalized = StringUtils.capitalize(SQL_CONFIGURATOR_CLASS_NAME);
                sqlConfiguratorClassName = ServletParametersStore.getInitParameter(servletName, capitalized);
            }

            // Call the specific Configurator class to use

            classNameToLoad = commonsConfiguratorClassName;
            if (commonsConfiguratorClassName != null && !commonsConfiguratorClassName.isEmpty()) {
                Class<?> c = Class.forName(commonsConfiguratorClassName);
                commonsConfigurator = (CommonsConfigurator) c.newInstance();
            } else {

                commonsConfigurator = new DefaultCommonsConfigurator();

            }

            // Immediately create the ServerLogger
            Logger logger = null;
            try {
                logger = commonsConfigurator.getLogger();
                ServerLogger.createLogger(logger);
                serverLoggerOk = true;
            } catch (Exception e) {
                exception = e;
                initErrrorMesage = Tag.PRODUCT_USER_CONFIG_FAIL + " Impossible to create the Logger: " + logger
                        + ". Reason: " + e.getMessage();
            }

            classNameToLoad = fileConfiguratorClassName;
            if (fileConfiguratorClassName != null && !fileConfiguratorClassName.isEmpty()) {
                Class<?> c = Class.forName(fileConfiguratorClassName);
                fileConfigurator = (FileConfigurator) c.newInstance();
            } else {
                fileConfigurator = new DefaultFileConfigurator();
            }

            classNameToLoad = sqlConfiguratorClassName;
            if (sqlConfiguratorClassName != null && !sqlConfiguratorClassName.isEmpty()) {
                Class<?> c = Class.forName(sqlConfiguratorClassName);
                sqlConfigurator = (SqlConfigurator) c.newInstance();
            } else {
                sqlConfigurator = new DefaultSqlConfigurator();
            }

        } catch (ClassNotFoundException e) {
            initErrrorMesage = Tag.PRODUCT_USER_CONFIG_FAIL
                    + " Impossible to load (ClassNotFoundException) Configurator class: " + classNameToLoad;
            exception = e;
        } catch (InstantiationException e) {
            initErrrorMesage = Tag.PRODUCT_USER_CONFIG_FAIL
                    + " Impossible to load (InstantiationException) Configurator class: " + classNameToLoad;
            exception = e;
        } catch (IllegalAccessException e) {
            initErrrorMesage = Tag.PRODUCT_USER_CONFIG_FAIL
                    + " Impossible to load (IllegalAccessException) Configurator class: " + classNameToLoad;
            exception = e;
        } catch (SqlConfigurationException e) {
            initErrrorMesage = e.getMessage();
            exception = e;
        } catch (Exception e) {
            initErrrorMesage = Tag.PRODUCT_PRODUCT_FAIL + " Please contact support at: support@kawansoft.com";
            exception = e;
        }

        if (commonsConfigurator == null) {
            commonsConfiguratorClassName = COMMONS_CONFIGURATOR_CLASS_NAME;
        } else {
            commonsConfiguratorClassName = commonsConfigurator.getClass().getName();
        }

        if (fileConfigurator == null) {
            fileConfiguratorClassName = FILE_CONFIGURATOR_CLASS_NAME;
        } else {
            fileConfiguratorClassName = fileConfigurator.getClass().getName();
        }

        if (sqlConfigurator == null) {
            sqlConfiguratorClassName = SQL_CONFIGURATOR_CLASS_NAME;
        } else {
            sqlConfiguratorClassName = sqlConfigurator.getClass().getName();
        }

        System.out.println(SqlTag.SQL_PRODUCT_START + " " + servletName + " Servlet Configurators:");
        System.out.println(
                SqlTag.SQL_PRODUCT_START + "  -> commonsConfiguratorClassName: " + commonsConfiguratorClassName);
        System.out.println(
                SqlTag.SQL_PRODUCT_START + "  -> sqlConfiguratorClassName    : " + sqlConfiguratorClassName);
        System.out.println(
                SqlTag.SQL_PRODUCT_START + "  -> fileConfiguratorClassName   : " + fileConfiguratorClassName);

        if (exception == null) {
            System.out.println(SqlTag.SQL_PRODUCT_START + "  -> Configurators Status: OK.");
        } else {

            if (!TomcatModeStore.isTomcatEmbedded()) {
                String errorMessage1 = SqlTag.SQL_PRODUCT_START + "  -> Configurators Status: KO.";
                String errorMessage2 = initErrrorMesage;
                String errorMessage3 = ExceptionUtils.getStackTrace(exception);

                System.out.println(errorMessage1);
                System.out.println(errorMessage2);
                System.out.println(errorMessage3);

                if (serverLoggerOk) {
                    ServerLogger.getLogger().log(Level.WARNING, errorMessage1);
                    ServerLogger.getLogger().log(Level.WARNING, errorMessage2);
                    ServerLogger.getLogger().log(Level.WARNING, errorMessage3);
                }

                System.out.println();
            }

        }
    }

    /**
     * Test the configurators main methods to see if they throw Exceptions
     */

    /**
     * Get request.
     */
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {

        request.setCharacterEncoding("UTF-8");
        // Store the host info in RequestInfoStore
        RequestInfoStore.init(request);

        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        String servletName = this.getServletName();

        if (commonsConfigurator != null) {
            debug("doGet commonsConfigurator: " + commonsConfigurator.getClass().getName());
        } else {
            debug("doGet commonsConfigurator is null");
        }

        if (fileConfigurator != null) {
            debug("doGet fileConfigurator   : " + fileConfigurator.getClass().getName());
        } else {
            debug("doGet fileConfigurator is null");
        }

        if (sqlConfigurator != null) {
            debug("doGet sqlConfigurator    : " + sqlConfigurator.getClass().getName());
        } else {
            debug("doGet sqlConfigurator is null");
        }

        // Must be done in doPost() and do Get() because we need
        // request.getServerName()
        // That is not available in init...
        // checkOnceLicenseInfo(request, commonsConfigurator);

        ServerSqlManagerDoGetTester serverSqlManagerDoGetTester = new ServerSqlManagerDoGetTester();
        serverSqlManagerDoGetTester.doGetTest(servletName, out, exception, commonsConfigurator, fileConfigurator,
                sqlConfigurator);
    }

    /**
     * Post request.
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {

        request.setCharacterEncoding("UTF-8");
        // Store the host info in RequestInfoStore
        RequestInfoStore.init(request);

        // If init fail, say it cleanly to client, instead of bad 500 Servlet
        // Error
        if (exception != null) {
            OutputStream out = response.getOutputStream();

            writeLine(out, TransferStatus.SEND_FAILED);
            writeLine(out, exception.getClass().getName()); // Exception class
            // name
            writeLine(out, initErrrorMesage + " Reason: " + exception.getMessage()); // Exception
            // message
            writeLine(out, ExceptionUtils.getStackTrace(exception));

            return;

        }

        debug("after RequestInfoStore.init(request);");
        debug(request.getRemoteAddr());

        // Configure a repository (to ensure a secure temp location is used)
        ServletContext servletContext = this.getServletConfig().getServletContext();
        File servletContextTempDir = (File) servletContext.getAttribute("javax.servlet.context.tempdir");

        // Wrap the HttpServletRequest with HttpServletRequestEncrypted for
        // parameters decryption
        HttpServletRequestConvertor requestEncrypted = new HttpServletRequestConvertor(request,
                commonsConfigurator);

        ServerSqlDispatch dispatch = new ServerSqlDispatch();
        debug("before dispatch.executeRequest()");

        dispatch.executeRequest(requestEncrypted, response, servletContextTempDir, commonsConfigurator,
                fileConfigurator, sqlConfigurator);

    }

    /**
     * Write a line of string on the servlet output stream. Will add the
     * necessary CR_LF
     * 
     * @param out
     *            the servlet output stream
     * @param s
     *            the string to write
     * @throws IOException
     */
    public static void writeLine(OutputStream out, String s) throws IOException {
        out.write((s + CR_LF).getBytes());
    }

    /**
     * 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) {
            try {
                ServerLogger.getLogger().log(Level.WARNING, s);
            } catch (Exception e1) {
                System.out.println(s);
            }
        }
    }

}