Package org.gomba

Source Code of org.gomba.DatumServlet

package org.gomba;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Types;

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

import org.gomba.utils.xml.XMLTextReader;

/**
* Render a single datum accessed via JDBC. The SQL in the <code>query</code>
* init-param should be a SELECT and must return a resultset. The field to
* render must be non-null. This servlet inherits the init-params of
* {@link org.gomba.AbstractServlet}, plus:
* <dl>
* <dt>column</dt>
* <dd>The result set column to render. This init-param is required only if the
* result set contains more than one column. (Optional)</dd>
* <dt>media-type</dt>
* <dd>The resource MIME content type. May contain ${} parameters. (Required)
* </dd>
* </dl>
* <p>
* This servlet can handle the following HTTP methods: GET, HEAD.
* </p>
*
* @author Flavio Tordini
* @version $Id: DatumServlet.java,v 1.1.1.1 2004/06/16 13:15:12 flaviotordini
*                Exp $
*/
public class DatumServlet extends SingleQueryServlet {

    /**
     * The result set column name to render. May be null.
     */
    private String columnName;

    /**
     * The resource MIME content type.
     */
    private Expression mediaTypeExpression;

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

        // name of the column to render
        this.columnName = config.getInitParameter("column");

        // MIME
        String mediaTypeString = config.getInitParameter("media-type");
        if (mediaTypeString == null) {
            throw new ServletException("Missing init-param: media-type");
        }
        try {
            this.mediaTypeExpression = new Expression(mediaTypeString);
        } catch (Exception e) {
            throw new ServletException(
                    "Error parsing media type expression.", e);
        }
    }

    /**
     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
     *           javax.servlet.http.HttpServletResponse)
     */
    protected final void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response, true);
    }

    /**
     * @see javax.servlet.http.HttpServlet#doHead(javax.servlet.http.HttpServletRequest,
     *           javax.servlet.http.HttpServletResponse)
     */
    protected final void doHead(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response, false);
    }

    /**
     * @see org.gomba.AbstractServlet#doOutput(java.sql.ResultSet,
     *           javax.servlet.http.HttpServletResponse, ParameterResolver)
     */
    protected void doOutput(ResultSet resultSet, HttpServletResponse response,
            ParameterResolver parameterResolver) throws Exception {

        ResultSetMetaData rsmd = resultSet.getMetaData();
        if (rsmd.getColumnCount() != 1 && this.columnName == null) {
            throw new Exception(
                    "The result set contains more than one column. "
                            + "You need to set the 'column' init-param.");
        }

        // mime type
        final Object mediaType = this.mediaTypeExpression
                .replaceParameters(parameterResolver);
        if (!(mediaType instanceof java.lang.String)) {
            throw new Exception(
                    "The media-type expression does not evaluate to " + java.lang.String.class);
        }
        response.setContentType((String) mediaType);

        // find out the column index
        final int columnIndex;
        if (this.columnName != null) {
            columnIndex = getColumnIndex(rsmd, this.columnName);
        } else {
            columnIndex = 1;
        }

        final int columnType = rsmd.getColumnType(columnIndex);

        // render!
        switch (columnType) {

        case Types.BLOB:
            Blob blob = resultSet.getBlob(columnIndex);
            if (blob == null) {
                throw new Exception("BLOB value is null.");
            }
            streamBytes(blob.getBinaryStream(), response);
            break;

        case Types.CLOB:
            Clob clob = resultSet.getClob(columnIndex);
            if (clob == null) {
                throw new Exception("CLOB value is null.");
            }
            // wrap our reader in order to strip invalid XML chars
            Reader reader1 = new XMLTextReader(clob.getCharacterStream());
            streamCharacters(reader1, response);
            break;

        case Types.LONGVARCHAR:
        case Types.VARCHAR:
        case Types.CHAR:
            Reader reader2 = resultSet.getCharacterStream(columnIndex);
            if (reader2 == null) {
                throw new Exception("LONGVARCHAR value is null.");
            }
            // wrap our reader in order to strip invalid XML chars
          reader2 = new XMLTextReader(reader2);
            streamCharacters(reader2, response);
            break;

        case Types.LONGVARBINARY:
            InputStream is = resultSet.getBinaryStream(columnIndex);
            if (is == null) {
                throw new Exception("LONGVARBINARY value is null.");
            }
            streamBytes(is, response);
            break;

        default:
            String value = resultSet.getObject(columnIndex).toString();
            response.getWriter().write(value);
        }

    }

    /**
     * Get the index of a column in a resultset given its name.
     */
    protected static int getColumnIndex(ResultSetMetaData rsmd,
            String columnName) throws Exception {
        final int columnCount = rsmd.getColumnCount();
        for (int i = 1; i <= columnCount; i++) {
            // The set of columns begins with '1' rather than '0'
            final String cn = rsmd.getColumnName(i);
            if (cn.equalsIgnoreCase(columnName)) {
                return i;
            }
        }
        throw new Exception("Cannot find column named " + columnName);
    }

    /**
     * Stream unicode characters to the response body.
     *
     * @param reader
     *                   The stream of charachters
     * @param response
     *                   The HTTP response
     */
    private static void streamCharacters(Reader reader,
            HttpServletResponse response) throws IOException {
        try {
            char[] buffer = new char[response.getBufferSize()];
            Writer writer = response.getWriter();
            int length;
            while ((length = reader.read(buffer)) >= 0) {
                writer.write(buffer, 0, length);
            }
        } finally {
            reader.close();
        }
    }

    /**
     * Stream bytes to the response body.
     *
     * @param is
     *                   The stream of bytes
     * @param response
     *                   The HTTP response
     */
    private static void streamBytes(InputStream is, HttpServletResponse response)
            throws IOException {
        try {
            byte[] buffer = new byte[response.getBufferSize()];
            OutputStream os = response.getOutputStream();
            int length;
            while ((length = is.read(buffer)) >= 0) {
                os.write(buffer, 0, length);
            }
        } finally {
            is.close();
        }
    }

}
TOP

Related Classes of org.gomba.DatumServlet

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.