org.xmlactions.web.conceal.HttpPager.java Source code

Java tutorial

Introduction

Here is the source code for org.xmlactions.web.conceal.HttpPager.java

Source

/*
 * Copyright (C) Mike Murphy 2003-2015 <mike.murphy@xmlactions.org><mwjmurphy@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package org.xmlactions.web.conceal;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.xmlactions.action.Action;
import org.xmlactions.action.ActionConst;
import org.xmlactions.action.NestedActionException;
import org.xmlactions.action.config.IExecContext;
import org.xmlactions.common.xml.BadXMLException;
import org.xmlactions.pager.context.SessionExecContext;
import org.xmlactions.web.HttpParam;
import org.xmlactions.web.PagerWebConst;
import org.xmlactions.web.RequestExecContext;
import org.xmlactions.web.http.HttpSessionInfo;

/**
 * Servlet implementation class PagerServlet
 * <p>
 *  This class is used to manage http page requests.
 * </p>
 * <p>
 *  It uses an IExeContext that <b>must</b> be defined in the Spring ApplicationContext with id <b>"pager.execContext"</b>. This IExecContext is then extended with
 *  additional information such as
 *  <ul>
 *     <li>execContext.put(ActionConst.WEB_REAL_PATH_BEAN_REF, realPath);</li>
 *     <li>execContext.put(ActionConst.PAGE_NAMESPACE_BEAN_REF, nameSpace);</li>
 *     <li>execContext.setSession(request.getSession(true));</li>
 *     <li>execContext.loadFromPersistence();</li>
 *     <li>execContext.addNamedMap(IExecContext.PERSISTENCE_MAP, execContext.getPersistenceMap());</li>
 *     <li>execContext.addNamedMap(PagerWebConst.REQUEST, params);</li>
 *     <li>execContext.put(PagerWebConst.REQUEST_LIST, paramList);</li>
 *     <li>execContext.put(PagerWebConst.PAGE_NAME, (pageName.length() > 1 ? pageName.substring(1) : pageName));</li>
 *     <li>execContext.put(PagerWebConst.PAGE_URI, request.getRequestURI());</li>
 *     <li>execContext.put(PagerWebConst.PAGE_URL, request.getRequestURL()   .toString());</li>
 *     <li>execContext.put(PagerWebConst.PAGE_SERVER_NAME, request.getServerName());</li>
 *     <li>execContext.put(PagerWebConst.PAGE_APP_NAME, appName);</li>
 *     <li>execContext.put(ActionConst.WEB_ROOT_BEAN_REF, "");</li>
 *     <li>execContext.put(ActionConst.WEB_ROOT_BEAN_REF, "/" + appName);</li>
 *     <li>execContext.put(PagerWebConst.HTTP_REQUEST, request);</li>
 *     <li>execContext.put(PagerWebConst.HTTP_RESPONSE, response);</li>
 *     <li>execContext.put(PagerWebConst.HTTP_SESSION, request.getSession(true));</li>
 *     <li>execContext.put(PagerWebConst.EXEC_CONTEXT, execContext);</li>
 *    </ul>
 *  See PagerWebConst and org.xmlactions.action.ActionConst and org.xmlactions.action.config.IExecContext.
 * </p>
 * <p>
 *  The IExecContext is available from the code by calling org.xmlactions.web.RequestExecContext.get().
 * </p>
 */
public class HttpPager {

    private static final Logger log = LoggerFactory.getLogger(HttpPager.class);

    private static final String access_licence_file = "/config/pager/access.scr";
    private static final int[] p = new int[] { 2213, 1406, 2151, 375, 7445, 1666, 613, 2272, 3278, 743, 2619, 480,
            967, 3853, 1403, 2270 };

    // private static ApplicationContext applicationContext;

    // web site location on disk
    private static String realPath;

    private static String nameSpace;

    private static String wrapperPage;

    private static String prePage;
    private static String postPage;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public HttpPager() {

        super();
    }

    public static ApplicationContext getApplicationContext(ServletContext servletContext) {
        ApplicationContext applicationContext;
        applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
        return applicationContext;
    }

    /**
     * @see Servlet#init(ServletConfig)
     */
    public void init(ServletConfig config) throws ServletException {

        String value;

        value = config.getServletContext().getRealPath("");
        if (StringUtils.isNotEmpty(value)) {
            realPath = value;
        }

        value = config.getInitParameter("pager.namespace");
        if (StringUtils.isNotEmpty(value)) {
            nameSpace = value;
        }

        value = config.getInitParameter("pager.wrapperPage");
        if (StringUtils.isNotEmpty(value)) {
            wrapperPage = value;
        }

        value = config.getInitParameter("pager.pre.page");
        if (StringUtils.isNotEmpty(value)) {
            prePage = value;
        }

        value = config.getInitParameter("pager.post.page");
        if (StringUtils.isNotEmpty(value)) {
            postPage = value;
        }

        // applicationContext =
        // WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext());
    }

    /**
     * @see Servlet#init(ServletConfig)
     */
    public void init(FilterConfig filterConfig) {

        String value;
        value = filterConfig.getInitParameter("pager.realPath");
        if (StringUtils.isEmpty(value)) {
            value = filterConfig.getServletContext().getRealPath("");
        }
        if (StringUtils.isNotEmpty(value)) {
            realPath = value;
        }

        value = filterConfig.getInitParameter("pager.namespace");
        if (StringUtils.isNotEmpty(value)) {
            nameSpace = value;
        }

        value = filterConfig.getInitParameter("pager.wrapperPage");
        if (StringUtils.isNotEmpty(value)) {
            wrapperPage = value;
        }

        value = filterConfig.getInitParameter("pager.pre.page");
        if (StringUtils.isNotEmpty(value)) {
            prePage = value;
        }

        value = filterConfig.getInitParameter("pager.post.page");
        if (StringUtils.isNotEmpty(value)) {
            postPage = value;
        }
    }

    public SessionExecContext setupExecContext(HttpServletRequest request, HttpServletResponse response)
            throws IOException, FileUploadException {

        ApplicationContext applicationContext = getApplicationContext(request.getSession(true).getServletContext());

        SessionExecContext execContext = (SessionExecContext) applicationContext
                .getBean(ActionConst.EXEC_CONTEXT_BEAN_REF);

        new CreateHandyParams(execContext);

        // Make it available for the scope of this request.
        RequestExecContext.set(execContext);

        execContext.setApplicationContext(applicationContext);

        execContext.put(ActionConst.WEB_REAL_PATH_BEAN_REF, realPath);
        execContext.put(ActionConst.PAGE_NAMESPACE_BEAN_REF, nameSpace);

        execContext.setSession(request.getSession(true));
        execContext.loadFromPersistence();
        execContext.addNamedMap(IExecContext.PERSISTENCE_MAP, execContext.getPersistenceMap());
        new CreateUserParams(execContext);

        // FIXME - will want to remove the addNamedMap("request")
        Map<String, Object> params = new HtmlRequestMapper(-1).getRequestParamsAsMap(request);
        if (params != null) {
            execContext.addNamedMap(PagerWebConst.REQUEST, params);
        }
        List<HttpParam> paramList = new HtmlRequestMapper(-1).getRequestParamsAsVector(request);
        if (paramList != null) {
            execContext.put(PagerWebConst.REQUEST_LIST, paramList);
        }
        String pageName = request.getServletPath();
        // remove the leading slash/
        execContext.put(PagerWebConst.PAGE_NAME, (pageName.length() > 1 ? pageName.substring(1) : pageName));
        execContext.put(PagerWebConst.PAGE_URI, request.getRequestURI());
        execContext.put(PagerWebConst.PAGE_URL, request.getRequestURL().toString());
        execContext.put(PagerWebConst.PAGE_SERVER_NAME, request.getServerName());
        String appName = getAppName(request.getRequestURI());
        execContext.put(PagerWebConst.PAGE_APP_NAME, appName);
        if (StringUtils.isEmpty(appName)) {
            execContext.put(ActionConst.WEB_ROOT_BEAN_REF, "");
        } else {
            execContext.put(ActionConst.WEB_ROOT_BEAN_REF, "/" + appName);
        }
        execContext.put(PagerWebConst.HTTP_REQUEST, request);
        execContext.put(PagerWebConst.HTTP_RESPONSE, response);
        execContext.put(PagerWebConst.HTTP_SESSION, request.getSession(true));
        execContext.put(PagerWebConst.EXEC_CONTEXT, execContext);

        // log.debug(((PropertyContainer)
        // webApplicationContext.getBean("readOnlyProperties")).get("user.home"));
        log.debug("nameSpace:" + nameSpace);
        log.debug("Real Path:" + realPath);
        log.debug("bean count:" + execContext.getApplicationContext().getBeanDefinitionCount());
        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            log.debug("bean:" + beanName);
            execContext.put(beanName, applicationContext.getBean(beanName));
        }

        execContext.addNamedMap(PagerWebConst.REQUEST_HEADERS, HttpSessionInfo.getRequestHeaders(request));

        log.info("ExecContext size:" + execContext.size());

        return execContext;
    }

    public static SessionExecContext setupExecContext(ServletContext servletContext)
            throws IOException, FileUploadException {

        ApplicationContext applicationContext = getApplicationContext(servletContext);

        SessionExecContext execContext = (SessionExecContext) applicationContext
                .getBean(ActionConst.EXEC_CONTEXT_BEAN_REF);

        new CreateHandyParams(execContext);
        new CreateUserParams(execContext);

        // execContext.reset();
        RequestExecContext.set(execContext);

        // Make it available for the scope of this request.

        execContext.setApplicationContext(applicationContext);

        execContext.put(ActionConst.WEB_REAL_PATH_BEAN_REF, realPath);
        execContext.put(ActionConst.PAGE_NAMESPACE_BEAN_REF, nameSpace);

        // remove the leading slash/
        execContext.put(PagerWebConst.EXEC_CONTEXT, execContext);

        log.debug("nameSpace:" + nameSpace);
        log.debug("Real Path:" + realPath);
        log.debug("bean count:" + execContext.getApplicationContext().getBeanDefinitionCount());
        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            log.debug("bean:" + beanName);
            execContext.put(beanName, applicationContext.getBean(beanName));
        }

        log.info("ExecContext size:" + execContext.size());

        return execContext;
    }

    public void processPage(ServletRequest request, ServletResponse response, String page)
            throws ServletException, IOException {
        IExecContext execContext = null;
        if (response instanceof HttpServletResponse && request instanceof HttpServletRequest) {
            try {
                HttpServletRequest httpServletRequest = (HttpServletRequest) request;
                HttpServletResponse httpServletResponse = (HttpServletResponse) response;

                execContext = setupExecContext(httpServletRequest, httpServletResponse);

                String pageName = httpServletRequest.getServletPath();

                if (pageName.indexOf("axelconfig") > 0) {
                    PrintWriter out = response.getWriter();
                    out.print(buildInfo(httpServletRequest, httpServletResponse));
                    out.close();
                    return;
                }

                if (!pageName.endsWith(".ajax")) {

                    String alternatePage = processPrePages(execContext, httpServletRequest, httpServletResponse);
                    if ("stop".equals(execContext.getString("pre.page.stop"))) {
                        execContext.put("pre.page.stop", "");
                        response.setContentType("text/html;charset=UTF-8");

                        PrintWriter out = response.getWriter();
                        out.print(alternatePage);
                        out.close();
                    }
                }

                log.debug("contextPath:" + httpServletRequest.getContextPath());
                log.debug("URI:" + httpServletRequest.getRequestURI());
                log.debug("root:" + realPath + " page:" + pageName + " wrapperPage:" + wrapperPage);
                log.debug(HttpSessionInfo.sysInfo(httpServletRequest));
                Action action;
                if (pageName.endsWith(".ajax")) {
                    page = processAjaxCall(httpServletRequest, httpServletResponse,
                            pageName.substring(1, pageName.length() - ".ajax".length()), execContext);
                    page = StrSubstitutor.replace(page, execContext);
                } else if (pageName.endsWith(".bin") || pageName.endsWith(".pdfbin")) {
                    String pn = null;
                    if (pageName.endsWith(".pdfbin")) {
                        pn = pageName.substring(1, pageName.length() - ".pdfbin".length());
                    } else {
                        pn = pageName.substring(1, pageName.length() - ".bin".length());
                    }
                    page = processAjaxCall(httpServletRequest, httpServletResponse, pn, execContext);

                    if (page.startsWith("EX:")) {
                        PrintWriter out = response.getWriter();
                        out.print(page);
                        out.close();
                    } else {
                        byte[] image = (byte[]) execContext.get("image");
                        if (pageName.endsWith(".pdfbin")) {
                            String outputPdfFileName = execContext.getString("outputFileName");
                            String ex = serviceJasperPdfRequest(httpServletResponse, image, outputPdfFileName);
                            if (ex != null) {
                                PrintWriter out = response.getWriter();
                                out.print(page);
                                out.close();
                            }
                            return;
                        } else {

                            String responseType = execContext.getString("response_type");
                            if (StringUtils.isEmpty(responseType)) {
                                responseType = "image/png";
                            }
                            response.setContentType(responseType);

                            processPostPages(execContext, httpServletRequest, httpServletResponse);

                            InputStream in = new ByteArrayInputStream(image);
                            OutputStream out = response.getOutputStream();

                            // Copy the contents of the file to the output
                            // stream
                            byte[] buf = new byte[1024];
                            int count = 0;
                            while ((count = in.read(buf)) >= 0) {
                                out.write(buf, 0, count);
                            }
                            in.close();
                            out.close();
                        }
                        return;
                    }
                } else {
                    if (pageName.startsWith("/:")) {
                        String wrapperPageName = null;
                        int secondColon = pageName.indexOf(':', 2);
                        if (secondColon >= 0) {
                            wrapperPageName = pageName.substring(2, secondColon);
                            execContext.put("inner_page", "/" + pageName.substring(secondColon + 1));
                        } else {
                            if (StringUtils.isEmpty(wrapperPage)) {
                                throw new ServletException("No wrapper page set, why use :");
                            }
                            wrapperPageName = wrapperPage;
                            execContext.put("inner_page", "/" + pageName.substring(2));
                        }
                        // insert the requested page into the wrapper page
                        action = new Action(realPath, wrapperPageName, nameSpace);
                    } else {
                        if (StringUtils.isNotEmpty(wrapperPage)) {
                            // we have a base wrapper page defined
                            execContext.put("inner_page", "/" + pageName);
                            action = new Action(realPath, wrapperPage, nameSpace);
                        } else {
                            if (pageName.indexOf("show_axel_config") >= 0) {
                                page = AxelConfig.getAxelConfig(execContext);
                                log.info(page);
                                page = "Config Copied to Log";
                                action = null;
                            } else {
                                // if we don't have a wrapper page we show the requested page
                                action = new Action(realPath, pageName, nameSpace);
                            }
                        }
                    }
                    if (action != null) {
                        if (StringUtils.isNotEmpty(page)) {
                            page = action.processPage(execContext, page);
                        } else {
                            page = action.processPage(execContext);
                        }
                    }
                }

                log.debug("URI:" + httpServletRequest.getRequestURI());
                // log.debug("page:" + page);
                Object object = execContext.get(ActionConst.NO_STR_SUBST);
                // log.debug(ActionConst.NO_STR_SUBST + ":[" + object + "]");
                execContext.put(ActionConst.NO_STR_SUBST, null);

                if (pageName.toLowerCase().endsWith("soap")) {
                    response.setContentType(IExecContext.CONTENT_TYPE_XML);

                } else if (pageName.toLowerCase().endsWith("json")) {
                    response.setContentType(IExecContext.CONTENT_TYPE_JSON);

                } else {
                    response.setContentType(IExecContext.CONTENT_TYPE_HTML);
                }

                processPostPages(execContext, httpServletRequest, httpServletResponse);

                // = = =
                // check if there is a contentType value stored in the execContext.  This could have been set by one of the actions such as an action that wants to return a JSON data.
                // = = =
                String contentType = execContext.getString(IExecContext.CONTENT_TYPE_KEY);
                if (StringUtils.isNotBlank(contentType)) {
                    response.setContentType(contentType);
                    //               if (contentType.equals(IExecContext.CONTENT_TYPE_JSON) || contentType.equals(IExecContext.CONTENT_TYPE_XML)) {
                    //                  if (response instanceof HttpServletResponse) {
                    //                     ((HttpServletResponse)response).setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1
                    //                     ((HttpServletResponse)response).setHeader("Pragma", "no-cache"); // HTTP 1.0
                    //                     ((HttpServletResponse)response).setDateHeader("Expires", 0); // Proxies.
                    //                  }
                    //               }
                }
                execContext.remove("content_type");
                PrintWriter out = response.getWriter();
                out.print(page);
                out.close();

            } catch (Throwable t) {
                // TODO review this, use a better way for reporting the error.
                log.info(t.getMessage(), t);
                throw new ServletException(t);
            } finally {
                if (execContext != null) {
                    execContext.saveToPersistence();
                    RequestExecContext.remove();
                }
            }
        } else {
            String msg = "Not processing page. Must be HttpServletRequest not [" + request.getClass().getName()
                    + "] and HttpServletResponse not [" + response.getClass().getName() + "]";

            log.info(msg);
            throw new ServletException(msg);
        }
    }

    private String processAjaxCall(HttpServletRequest request, HttpServletResponse response, String pageName,
            IExecContext execContext) {

        try {
            if (pageName.indexOf('/') >= 0) {
                pageName = pageName.substring(pageName.lastIndexOf('/') + 1);
            }
            String xml = "<" + nameSpace + ":" + pageName + " />";
            log.debug("processAjaxCall - pageName:" + pageName + " xml:" + xml);
            Action action = new Action(realPath, null, nameSpace);
            return action.processPage(execContext, xml);
        } catch (Exception ex) {
            return ("EX:" + ex.getMessage() + (ex.getCause() != null ? "\n" + ex.getCause() : ""));
        }

    }

    /**
     * Process a page from a filter chain.
     */
    public void processPageFromFilter(ServletRequest request, ServletResponse response, String page)
            throws ServletException, IOException {
        if (StringUtils.isEmpty(page)) {
            return;
        }
        processPage(request, response, page);
    }

    private String processPrePages(IExecContext execContext, HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse)
            throws IOException, NestedActionException, ClassNotFoundException, InstantiationException,
            IllegalAccessException, InvocationTargetException, NoSuchMethodException, BadXMLException {

        String page = null;
        String pageName = prePage;
        if (StringUtils.isNotEmpty(pageName)) {
            Action action;
            action = new Action(realPath, pageName, nameSpace);
            page = action.processPage(execContext);
        }
        return page;
    }

    private void processPostPages(IExecContext execContext, HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse)
            throws IOException, NestedActionException, ClassNotFoundException, InstantiationException,
            IllegalAccessException, InvocationTargetException, NoSuchMethodException, BadXMLException {

        String pageName = postPage;
        if (StringUtils.isNotEmpty(pageName)) {
            Action action;
            action = new Action(realPath, pageName, nameSpace);
            String page = action.processPage(execContext);
        }

    }

    private String getAppName(String uri) {
        if (uri.startsWith("/") && uri.indexOf('/', 1) > 0) {
            String[] parts = uri.split("/");
            return parts[1];
        } else if (uri.startsWith("/") == false && uri.indexOf('/') > 0) {
            String[] parts = uri.split("/");
            return parts[0];
        }
        return uri;

    }

    private String serviceJasperPdfRequest(HttpServletResponse response, byte[] pdfImage,
            String outputPdfFileName) {

        InputStream inputStream = null;
        OutputStream responseOutputStream = null;
        try {
            response.setContentType("application/pdf");
            response.addHeader("Content-Disposition", "attachment; filename=" + outputPdfFileName);
            response.setContentLength(pdfImage.length);

            inputStream = new ByteArrayInputStream(pdfImage);
            responseOutputStream = response.getOutputStream();
            int bytes;
            while ((bytes = inputStream.read()) != -1) {
                responseOutputStream.write(bytes);
            }
        } catch (Exception ex) {
            return ("EX:" + ex.getMessage());
        } finally {
            IOUtils.closeQuietly(inputStream);
            // IOUtils.closeQuietly(responseOutputStream);
        }
        return null;
    }

    private String buildInfo(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        StringBuilder page = new StringBuilder();

        page.append("<html>");

        File cd = new File("");
        page.append("<li>cd:" + cd.getAbsolutePath() + "</li>");
        page.append("<li>contextPath:" + httpServletRequest.getContextPath() + "</li>");
        page.append("<li>URI:" + httpServletRequest.getRequestURI() + "</li>");
        page.append("<li>root:" + realPath + " wrapperPage:" + wrapperPage + "</li>");
        page.append("<p>" + HttpSessionInfo.sysInfo(httpServletRequest) + "</p>");

        page.append("</html>");
        return page.toString();
    }

}