Package org.gomba

Source Code of org.gomba.AbstractServlet

package org.gomba;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.gomba.utils.servlet.ServletParameterUtils;

/**
* Base class for Servlets that render data accessed via JDBC.
* <p>
* Context params:
* <dl>
* <dt>org.gomba.dataSource</dt>
* <dd>The default JNDI data source. If not specified, the data source must be
* set in the <code>data-source</code> servlet init-param. (Optional)</dd>
* </dl>
* <dl>
* <dt>org.gomba.debug</dt>
* <dd>The default debug mode. To enable debug logging set the value to 'true'.
* (Optional)</dd>
* </dl>
* </p>
*
* <p>
* This servlet inherits the init-params of
* {@link org.gomba.TransactorAbstractServlet}
* </p>
*
* </p>
* Init params:
* <dl>
* <dt>data-source</dt>
* <dd>The JNDI data source. The default data source may be specified in the
* <code>org.gomba.dataSource</code> context-param. (Optional)</dd>
* <dt>response-headers</dt>
* <dd>The HTTP response headers in Java Properties format. May contain ${}
* parameters in the property values. It is highly recommended to set this
* init-param, especially for cache headers like "Last-modified", "Expires" etc.
* (Optional)</dd>
* <dt>http-status</dt>
* <dd>The HTTP status code to send when the request is successfully processed.
* Defaults to 200 (OK). (Optional)</dd>
* <dt>multipart-size-threshold</dt>
* <dd>The size threshold beyond which files are written directly to disk.
* Defaut: 64K (Optional)</dd>
* <dt>multipart-max-size</dt>
* <dd>The maximum allowed upload size. If negative, there is no maximum.
* Defaut: 128K (Optional)</dd>
* <dt>multipart-repository-path</dt>
* <dd>The location used to temporarily store files that are larger than the
* configured size threshold. Defaut: the system default temp directory, as
* returned by System.getProperty("java.io.tmpdir") (Optional)</dd>
* <dt>debug</dt>
* <dd>Log debug mode. To enable debug logging set the value to 'true'. The
* default debug mode may be specified in the <code>org.gomba.debug</code>
* context-param. (Optional)</dd>
* </dl>
* </p>
*
* @author Flavio Tordini
* @version $Id: AbstractServlet.java,v 1.2 2004/06/28 16:12:05 flaviotordini
*                Exp $
*/
abstract class AbstractServlet extends TransactorAbstractServlet {

    private final static String CONTEXT_PARAM_DATA_SOURCE = "org.gomba.dataSource";

    protected final static String CONTEXT_PARAM_DEBUG = "org.gomba.debug";

    protected final static String INIT_PARAM_DEBUGMODE = "debug";

    private final static String INIT_PARAM_DATA_SOURCE = "data-source";

    private final static String INIT_PARAM_RESPONSE_HEADERS = "response-headers";

    private final static String INIT_PARAM_HTTP_STATUS = "http-status";

    private final static String INIT_PARAM_MULTIPART_SIZE_THRESHOLD = "multipart-size-threshold";

    private final static String INIT_PARAM_MULTIPART_MAX_SIZE = "multipart-max-size";

    private final static String INIT_PARAM_MULTIPART_REPOSITORY_PATH = "multipart-repository-path";

    private final static String APP_NAME = "Gomba";

    static {

        // get version
        InputStream is = AbstractServlet.class.getClassLoader()
                .getResourceAsStream("org/gomba/version.properties");

        Properties version = new Properties();
        try {
            version.load(is);
            is.close();
        } catch (IOException ioe) {
            System.err.println(AbstractServlet.class.getName()
                    + ": Cannot load version information.");
            ioe.printStackTrace();
        }

        String major = version.getProperty("major");
        String minor = version.getProperty("minor");
        String micro = version.getProperty("micro");

        System.out.println(APP_NAME + ' ' + major + '.' + minor + '.' + micro
                + " http://gomba.sourceforge.net/");

    }

    /**
     * <code>true</code> if debug logging is turned on.
     */
    private boolean debugMode;

    /**
     * The data source to query.
     */
    private DataSource dataSource;

    /**
     * Map HTTP response header name to an {@link Expression}. May be null.
     */
    private Map responseHeaders;

    /**
     * The HTTP status code when the request is successfully processed.
     */
    private int httpStatusCode = HttpServletResponse.SC_OK;

    private int multipartSizeThreshold = 1024 * 64;

    private int multipartMaxSize = 1024 * 128;

    private String multipartRepositoryPath;

    /**
     * @return <code>true</code> if debug is enabled.
     */
    protected static boolean getDebugMode(ServletConfig config) {
        boolean debugMode;
        String debugStr = config.getInitParameter(INIT_PARAM_DEBUGMODE);
        if (debugStr != null) {
            debugMode = Boolean.valueOf(debugStr).booleanValue();
        } else {
            debugMode = Boolean.valueOf(
                    config.getServletContext().getInitParameter(
                            CONTEXT_PARAM_DEBUG)).booleanValue();
        }
        return debugMode;
    }

    /**
     * @return The JDBC DataSource for this servlet instance.
     */
    protected static DataSource getDataSource(ServletConfig config)
            throws ServletException {

        DataSource dataSource;

        String dataSourceName = config.getInitParameter(INIT_PARAM_DATA_SOURCE);
        if (dataSourceName == null) {
            dataSourceName = config.getServletContext().getInitParameter(
                    CONTEXT_PARAM_DATA_SOURCE);
        }
        if (dataSourceName == null) {
            throw new ServletException(
                    "JDBC data source not specified. Please set the '"
                            + CONTEXT_PARAM_DATA_SOURCE
                            + "' context-param or the '"
                            + INIT_PARAM_DATA_SOURCE + "' servlet init-param.");
        }
        try {
            Context initContext = new InitialContext();
            Context envContext = (Context) initContext.lookup("java:/comp/env");
            dataSource = (DataSource) envContext.lookup(dataSourceName);
        } catch (NamingException ne) {
            throw new ServletException(
                    "Error getting reference to data source.", ne);
        }

        return dataSource;
    }

    /**
     * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
     */
    public void init(ServletConfig config) throws ServletException {
        super.init(config);

        // debug mode
        this.debugMode = getDebugMode(config);

        // get the JNDI data source
        this.dataSource = getDataSource(config);

        // parse the response header settings
        try {
            this.responseHeaders = parseResponseHeaderSettings(config
                    .getInitParameter(INIT_PARAM_RESPONSE_HEADERS));
        } catch (Exception e) {
            throw new ServletException(
                    "Error parsing response header settings.", e);
        }

        // the HTTP status code to send when everything's alright.
        try {
            String httpStatusCodeString = config
                    .getInitParameter(INIT_PARAM_HTTP_STATUS);
            if (httpStatusCodeString != null) {
                this.httpStatusCode = Integer.parseInt(httpStatusCodeString);
            }
        } catch (NumberFormatException e) {
            throw new ServletException("Error parsing "
                    + INIT_PARAM_HTTP_STATUS, e);
        }

        // the multipart size threshold between memory and disk based storage
        try {
            String multipartSizeThresholdString = config
                    .getInitParameter(INIT_PARAM_MULTIPART_SIZE_THRESHOLD);
            if (multipartSizeThresholdString != null) {
                this.multipartSizeThreshold = Integer
                        .parseInt(multipartSizeThresholdString);
            }
        } catch (NumberFormatException e) {
            throw new ServletException("Error parsing "
                    + INIT_PARAM_MULTIPART_SIZE_THRESHOLD, e);
        }

        // the multipart max size
        try {
            String multipartMaxSizeString = config
                    .getInitParameter(INIT_PARAM_MULTIPART_MAX_SIZE);
            if (multipartMaxSizeString != null) {
                this.multipartMaxSize = Integer
                        .parseInt(multipartMaxSizeString);
            }
        } catch (NumberFormatException e) {
            throw new ServletException("Error parsing "
                    + INIT_PARAM_MULTIPART_MAX_SIZE, e);
        }

        // The multipart repository path
        this.multipartRepositoryPath = config
                .getInitParameter(INIT_PARAM_MULTIPART_REPOSITORY_PATH);

    }

    /**
     * Get a Query instance for our QueryDefinition.
     */
    protected Query getQuery(QueryDefinition requestQueryDefinition,
            ParameterResolver parameterResolver) throws ServletException {
        // build the Query
        final Query query;
        try {
            query = new Query(requestQueryDefinition, parameterResolver);
            // debug queries
            if (this.debugMode) {
                log("Query: " + query);
            }
        } catch (Exception e) {
            throw new ServletException("Error building query.", e);
        }
        return query;
    }

    /**
     * Ensure the resultset cursor is positioned on a row.
     *
     * @return true if the ResultSet is positioned on a row. if the ResultSet
     *               contains no rows return false.
     */
    protected final static boolean maybeMoveCursor(ResultSet resultSet)
            throws SQLException {

        if (resultSet.isBeforeFirst()) {
            // we're before the first row
            if (!resultSet.next()) {
                // 0 rows in this result set
                return false;
            }

        } else if (resultSet.getRow() == 0) {
            // no current row (we should be after the last row)
            return false;
        }

        return true;
    }

    /**
     * Parse the response header settings.
     *
     * @param settings
     *                   Response header in Java Properties format.
     * @return Map the response header name to its dynamic value. Mapping is
     *               String to {@link Expression}
     * @throws Exception
     */
    private final static Map parseResponseHeaderSettings(String settings)
            throws Exception {
        if (settings == null) {
            return null;
        }
        Properties headers = new Properties();
        InputStream inputStream = new ByteArrayInputStream(settings.getBytes());
        try {
            headers.load(inputStream);
        } finally {
            inputStream.close();
        }

        final Map responseHeaders = new HashMap(headers.size(), 1);

        Enumeration headerNames = headers.propertyNames();
        while (headerNames.hasMoreElements()) {
            String headerName = (String) headerNames.nextElement();
            String headerValue = headers.getProperty(headerName);
            responseHeaders.put(headerName, new Expression(headerValue));
        }

        // make responseHeaders immutable
        return Collections.unmodifiableMap(responseHeaders);

    }

    protected final static void setResponseHeader(HttpServletResponse response,
            String headerName, Object headerValue) {
        if (headerValue instanceof java.util.Date) {
            response.setDateHeader(headerName, ((Date) headerValue).getTime());
        } else if (headerValue instanceof java.lang.Integer) {
            response.setIntHeader(headerName, ((Integer) headerValue)
                    .intValue());
        } else {
            response.setHeader(headerName, headerValue.toString());
        }
    }

    protected final void setResponseHeaders(HttpServletResponse response,
            ParameterResolver parameterResolver) throws ServletException {
        if (this.responseHeaders != null) {
            try {

                for (Iterator i = this.responseHeaders.entrySet().iterator(); i
                        .hasNext();) {
                    Map.Entry mapEntry = (Map.Entry) i.next();

                    String headerName = (String) mapEntry.getKey();
                    Object headerValue = ((Expression) mapEntry.getValue())
                            .replaceParameters(parameterResolver);

                    setResponseHeader(response, headerName, headerValue);
                }

            } catch (Exception e) {
                throw new ServletException("Error setting response headers.", e);
            }
        }
    }

    /**
     * Include a resource (a JSP) and capture its response body.
     *
     * @param queryResource
     *                   The resource to include
     * @param request
     *                   the HTTP request
     * @param response
     *                   the HTTP response
     * @return The captured resource response body.
     */
    protected final String getDynamicQuery(String queryResource,
            HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // get the dispatcher
        RequestDispatcher dispatcher = getServletContext()
                .getRequestDispatcher(queryResource);
        if (dispatcher == null) {
            throw new ServletException(
                    "Cannot get a RequestDispatcher for path: " + queryResource);
        }

        // set some useful information in the request
        request.setAttribute("path", ServletParameterUtils
                .getPathElements(request));

        // wrap the request in order to supply extra functionality (multiparm
        // form handling)
        CustomHttpServletRequestWrapper requestWrapper = new CustomHttpServletRequestWrapper(
                request, this.multipartSizeThreshold, this.multipartMaxSize,
                this.multipartRepositoryPath);

        // wrap our response, so we can capture the body (and the included
        // resource cannot mess with it)
        CustomHttpServletResponseWrapper responseWrapper = new CustomHttpServletResponseWrapper(
                response);

        // include the resource
        dispatcher.include(requestWrapper, responseWrapper);

        // and get the body
        String sql = responseWrapper.getBody();

        if (sql == null) {
            throw new ServletException("Can't happen! Dynamic query is null. "
                    + queryResource);
        }

        // trim SQL to minimize in order to make it more readable
        sql = sql.trim();

        return sql;
    }

    /**
     * @return Returns the dataSource.
     */
    protected DataSource getDataSource() {
        return this.dataSource;
    }

    /**
     * @return Returns the responseHeaders.
     */
    protected final Map getResponseHeaders() {
        return this.responseHeaders;
    }

    /**
     * @return Returns the debugMode.
     */
    protected final boolean isDebugMode() {
        return this.debugMode;
    }

    /**
     * @return Returns the httpStatusCode.
     */
    protected final int getHttpStatusCode() {
        return this.httpStatusCode;
    }

    /**
     * Utility method that returns profiling/debugging info for the current
     * request.
     *
     * @param request The current HTTP request
     * @param startTime The time when the processing has begun.
     */
    protected static String getProfilingMessage(HttpServletRequest request,
            long startTime) {
        final long processingTime = System.currentTimeMillis() - startTime;
        StringBuffer msg = new StringBuffer(request.getMethod());
        msg.append(' ');
        msg.append(request.getRequestURI());
        String qs = request.getQueryString();
        if (qs != null) {
            msg.append('?');
            msg.append(qs);
        }
        msg.append(" processed in ");
        msg.append(processingTime);
        msg.append("ms");
        return msg.toString();
    }

}
TOP

Related Classes of org.gomba.AbstractServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.