org.glom.web.server.OnlineGlomImagesServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.glom.web.server.OnlineGlomImagesServlet.java

Source

/*
 * Copyright (C) 2012 Openismus GmbH
 *
 * This file is part of GWT-Glom.
 *
 * GWT-Glom 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 3 of the License, or (at your
 * option) any later version.
 *
 * GWT-Glom 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 GWT-Glom.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.glom.web.server;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLConnection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.glom.web.server.libglom.Document;
import org.glom.web.shared.TypedDataItem;
import org.glom.web.shared.libglom.Field;
import org.glom.web.shared.libglom.layout.LayoutItem;
import org.glom.web.shared.libglom.layout.LayoutItemField;
import org.glom.web.shared.libglom.layout.LayoutItemImage;

import com.google.gwt.http.client.Response;
import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * @author Murray Cumming <murrayc@murrayc.com>
 * 
 */
public class OnlineGlomImagesServlet extends OnlineGlomServlet {

    private static final long serialVersionUID = 4001959815578006604L;

    public OnlineGlomImagesServlet() {
        super();
    }

    private void doError(HttpServletResponse resp, int errorCode, final String errorMessage) throws IOException {
        Log.error(errorMessage);
        resp.sendError(errorCode, errorMessage);
    }

    private void doError(HttpServletResponse resp, int errorCode, final String errorMessage,
            final String documentID) throws IOException {
        Log.error(documentID, errorMessage);
        resp.sendError(errorCode, errorMessage);
    }

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {

        //These match the history token keys in DetailsPlace:
        final String attrDocumentID = StringUtils.defaultString(req.getParameter("document"));
        final String attrTableName = StringUtils.defaultString(req.getParameter("table"));
        final String attrPrimaryKeyValue = StringUtils.defaultString(req.getParameter("value"));
        final String attrFieldName = StringUtils.defaultString(req.getParameter("field"));

        //To request a static LayoutItemImage from the document
        //instead of from the database:
        final String attrLayoutName = StringUtils.defaultString(req.getParameter("layout"));
        final String attrLayoutPath = StringUtils.defaultString(req.getParameter("layoutpath"));

        if (StringUtils.isEmpty(attrDocumentID)) {
            doError(resp, Response.SC_NOT_FOUND, "No document ID was specified.");
            return;
        }

        if (!isAuthenticated(req, attrDocumentID)) {
            doError(resp, Response.SC_NOT_FOUND, "No access to the document.", attrDocumentID);
            return;
        }

        if (StringUtils.isEmpty(attrTableName)) {
            doError(resp, Response.SC_NOT_FOUND, "No table name was specified.", attrDocumentID);
            return;
        }

        //TODO: Is it from the database or is it a static LayouteItemText from the document.

        final boolean fromDb = !StringUtils.isEmpty(attrPrimaryKeyValue);
        final boolean fromLayout = !StringUtils.isEmpty(attrLayoutName);

        if (!fromDb && !fromLayout) {
            doError(resp, Response.SC_NOT_FOUND, "No primary key value or layout name was specified.",
                    attrDocumentID);
            return;
        }

        if (fromDb && StringUtils.isEmpty(attrFieldName)) {
            doError(resp, Response.SC_NOT_FOUND, "No field name was specified.", attrDocumentID);
            return;
        }

        final ConfiguredDocument configuredDocument = getDocument(attrDocumentID);
        if (configuredDocument == null) {
            doError(resp, Response.SC_NOT_FOUND, "The specified document was not found.", attrDocumentID);
            return;
        }

        final Document document = configuredDocument.getDocument();
        if (document == null) {
            doError(resp, Response.SC_NOT_FOUND, "The specified document details were not found.", attrDocumentID);
            return;
        }

        byte[] bytes = null;
        if (fromDb) {
            bytes = getImageFromDatabase(req, resp, attrDocumentID, attrTableName, attrPrimaryKeyValue,
                    attrFieldName, configuredDocument, document);
        } else {
            bytes = getImageFromDocument(req, resp, attrDocumentID, attrTableName, attrLayoutName, attrLayoutPath,
                    configuredDocument, document);
        }

        if (bytes == null) {
            doError(resp, Response.SC_NOT_FOUND,
                    "The image bytes could not be found. Please see the earlier error.", attrDocumentID);
            return;
        }

        final InputStream is = new ByteArrayInputStream(bytes);
        final String contentType = URLConnection.guessContentTypeFromStream(is);
        resp.setContentType(contentType);

        // Set content size:
        resp.setContentLength((int) bytes.length);

        // Open the output stream:
        final OutputStream out = resp.getOutputStream();

        // Copy the contents to the output stream
        out.write(bytes);
        out.close();
    }

    /** Get the image from a specific <data_layout_text> node of a specific layout for a specific table in the document,
     * with no access to the database data.
     * 
     * @param resp
     * @param attrDocumentID
     * @param attrTableName
     * @param attrLayoutName
     * @param attrLayoutPath
     * @param configuredDocument
     * @param document
     * @return
     * @throws IOException 
     */
    private byte[] getImageFromDocument(final HttpServletRequest request, final HttpServletResponse resp,
            final String attrDocumentID, final String attrTableName, final String attrLayoutName,
            final String attrLayoutPath, final ConfiguredDocument configuredDocument, final Document document)
            throws IOException {
        final LayoutItem item = document.getLayoutItemByPath(attrTableName, attrLayoutName, attrLayoutPath);

        if (item == null) {
            doError(resp, Response.SC_NOT_FOUND,
                    "The item specifed by the layout path could not be found, attrLayoutPath=" + attrLayoutPath,
                    attrDocumentID);
            return null;
        }

        if (!(item instanceof LayoutItemImage)) {
            doError(resp, Response.SC_NOT_FOUND,
                    "The item specifed by the layout path is not an image. It has class: "
                            + item.getClass().getName() + " and item name=" + item.getName() + ", attrLayoutPath="
                            + attrLayoutPath,
                    attrDocumentID);
            return null;
        }

        final LayoutItemImage image = (LayoutItemImage) item;
        return image.getImage().getImageData();
    }

    /** Get the image from a specific field of a specific record in a specific table in the database.
     * 
     * @param resp
     * @param attrDocumentID
     * @param attrTableName
     * @param attrPrimaryKeyValue
     * @param attrFieldName
     * @param configuredDocument
     * @param document
     * @return
     * @throws IOException
     */
    private byte[] getImageFromDatabase(final HttpServletRequest request, final HttpServletResponse resp,
            final String attrDocumentID, final String attrTableName, final String attrPrimaryKeyValue,
            final String attrFieldName, final ConfiguredDocument configuredDocument, final Document document)
            throws IOException {
        final Field field = document.getField(attrTableName, attrFieldName);
        if (field == null) {
            doError(resp, Response.SC_NOT_FOUND, "The specified field was not found: field=" + attrFieldName,
                    attrDocumentID);
            return null;
        }

        final Field fieldPrimaryKey = document.getTablePrimaryKeyField(attrTableName);

        TypedDataItem primaryKeyValue = new TypedDataItem();
        primaryKeyValue.setNumber(Double.parseDouble(attrPrimaryKeyValue));

        final LayoutItemField layoutItemField = new LayoutItemField();
        layoutItemField.setFullFieldDetails(field);
        final List<LayoutItemField> fieldsToGet = new ArrayList<LayoutItemField>();
        fieldsToGet.add(layoutItemField);
        final String query = SqlUtils.buildSqlSelectWithKey(attrTableName, fieldsToGet, fieldPrimaryKey,
                primaryKeyValue, document.getSqlDialect());

        final ComboPooledDataSource authenticatedConnection = getConnection(request, attrDocumentID);
        if (authenticatedConnection == null) {
            return null;
        }

        ResultSet rs = null;
        try {
            rs = SqlUtils.executeQuery(authenticatedConnection, query);
        } catch (SQLException e) {
            doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
            return null;
        }

        if (rs == null) {
            doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "The SQL result set is null.", attrDocumentID);
            return null;
        }

        byte[] bytes = null;
        try {
            rs.next();
            bytes = rs.getBytes(1); //This is 1-indexed, not 0-indexed.
        } catch (SQLException e) {
            doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
            return null;
        }

        if (bytes == null) {
            doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "The database contained null.", attrDocumentID);
            return null;
        }

        return bytes;
    }
}