org.apache.flex.forks.velocity.runtime.resource.loader.DataSourceResourceLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.flex.forks.velocity.runtime.resource.loader.DataSourceResourceLoader.java

Source

package org.apache.flex.forks.velocity.runtime.resource.loader;

/*
 * Copyright 2001-2002,2004 The Apache Software Foundation.
 * 
 * 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.
 */

import java.io.InputStream;
import java.io.BufferedInputStream;
import java.util.Hashtable;

import javax.sql.DataSource;
import javax.naming.InitialContext;

import org.apache.flex.forks.velocity.runtime.Runtime;
import org.apache.flex.forks.velocity.runtime.resource.Resource;

import org.apache.flex.forks.velocity.exception.ResourceNotFoundException;

import org.apache.commons.collections.ExtendedProperties;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;

/**
 * This is a simple template file loader that loads templates
 * from a DataSource instead of plain files.
 *
 * It can be configured with a datasource name, a table name,
 * id column (name), content column (the template body) and a
 * datetime column (for last modification info).
 * <br>
 * <br>
 * Example configuration snippet for velocity.properties:
 * <br>
 * <br>
 * resource.loader = file, ds <br>
 * <br>
 * ds.resource.loader.public.name = DataSource <br>
 * ds.resource.loader.description = Velocity DataSource Resource Loader <br>
 * ds.resource.loader.class = org.apache.flex.forks.velocity.runtime.resource.loader.DataSourceResourceLoader <br>
 * ds.resource.loader.resource.datasource = java:comp/env/jdbc/Velocity <br>
 * ds.resource.loader.resource.table = tb_velocity_template <br>
 * ds.resource.loader.resource.keycolumn = id_template <br>
 * ds.resource.loader.resource.templatecolumn = template_definition <br>
 * ds.resource.loader.resource.timestampcolumn = template_timestamp <br>
 * ds.resource.loader.cache = false <br>
 * ds.resource.loader.modificationCheckInterval = 60 <br>
 * <br>
 * Example WEB-INF/web.xml: <br>
 * <br>
 *   <resource-ref> <br>
 *    <description>Velocity template DataSource</description> <br>
 *    <res-ref-name>jdbc/Velocity</res-ref-name> <br>
 *    <res-type>javax.sql.DataSource</res-type> <br>
 *    <res-auth>Container</res-auth> <br>
 *   </resource-ref> <br>
 * <br>
 *  <br>
 * and Tomcat 4 server.xml file: <br>
 *  [...] <br>
 *  <Context path="/exampleVelocity" docBase="exampleVelocity" debug="0"> <br>
 *  [...] <br>
 *   <ResourceParams name="jdbc/Velocity"> <br>
 *    <parameter> <br>
 *      <name>driverClassName</name> <br>
 *      <value>org.hsql.jdbcDriver</value> <br>
 *    </parameter> <br>
 *    <parameter> <br>
 *     <name>driverName</name> <br>
 *     <value>jdbc:HypersonicSQL:database</value> <br>
 *    </parameter> <br>
 *    <parameter> <br>
 *     <name>user</name> <br>
 *     <value>database_username</value> <br>
 *    </parameter> <br>
 *    <parameter> <br>
 *     <name>password</name> <br>
 *     <value>database_password</value> <br>
 *    </parameter> <br>
 *   </ResourceParams> <br>
 *  [...] <br>
 *  </Context> <br>
 *  [...] <br>
 * <br>
 *  Example sql script:<br>
 *  CREATE TABLE tb_velocity_template ( <br>
 *   id_template varchar (40) NOT NULL , <br>
 *   template_definition text (16) NOT NULL , <br>
 *   template_timestamp datetime NOT NULL  <br>
 *   ) <br>
 *
 * @author <a href="mailto:david.kinnvall@alertir.com">David Kinnvall</a>
 * @author <a href="mailto:paulo.gaspar@krankikom.de">Paulo Gaspar</a>
 * @author <a href="mailto:lachiewicz@plusnet.pl">Sylwester Lachiewicz</a>
 * @version $Id: DataSourceResourceLoader.java,v 1.8.8.1 2004/03/03 23:23:02 geirm Exp $
 */
public class DataSourceResourceLoader extends ResourceLoader {
    private String dataSourceName;
    private String tableName;
    private String keyColumn;
    private String templateColumn;
    private String timestampColumn;
    private InitialContext ctx;
    private DataSource dataSource;

    public void init(ExtendedProperties configuration) {
        dataSourceName = configuration.getString("resource.datasource");
        tableName = configuration.getString("resource.table");
        keyColumn = configuration.getString("resource.keycolumn");
        templateColumn = configuration.getString("resource.templatecolumn");
        timestampColumn = configuration.getString("resource.timestampcolumn");

        Runtime.info("Resources Loaded From: " + dataSourceName + "/" + tableName);
        Runtime.info(
                "Resource Loader using columns: " + keyColumn + ", " + templateColumn + " and " + timestampColumn);
        Runtime.info("Resource Loader Initalized.");
    }

    public boolean isSourceModified(Resource resource) {
        return (resource.getLastModified() != readLastModified(resource, "checking timestamp"));
    }

    public long getLastModified(Resource resource) {
        return readLastModified(resource, "getting timestamp");
    }

    /**
     * Get an InputStream so that the Runtime can build a
     * template with it.
     *
     *  @param name name of template
     *  @return InputStream containing template
     */
    public synchronized InputStream getResourceStream(String name) throws ResourceNotFoundException {
        if (name == null || name.length() == 0) {
            throw new ResourceNotFoundException("Need to specify a template name!");
        }

        try {
            Connection conn = openDbConnection();

            try {
                ResultSet rs = readData(conn, templateColumn, name);

                try {
                    if (rs.next()) {
                        return new BufferedInputStream(rs.getAsciiStream(templateColumn));
                    } else {
                        String msg = "DataSourceResourceLoader Error: cannot find resource " + name;
                        Runtime.error(msg);

                        throw new ResourceNotFoundException(msg);
                    }
                } finally {
                    rs.close();
                }
            } finally {
                closeDbConnection(conn);
            }
        } catch (Exception e) {
            String msg = "DataSourceResourceLoader Error: database problem trying to load resource " + name + ": "
                    + e.toString();

            Runtime.error(msg);

            throw new ResourceNotFoundException(msg);

        }

    }

    /**
     *  Fetches the last modification time of the resource
     *
     *  @param resource Resource object we are finding timestamp of
     *  @param i_operation string for logging, indicating caller's intention
     *
     *  @return timestamp as long
     */
    private long readLastModified(Resource resource, String i_operation) {
        /*
         *  get the template name from the resource
         */

        String name = resource.getName();
        try {
            Connection conn = openDbConnection();

            try {
                ResultSet rs = readData(conn, timestampColumn, name);
                try {
                    if (rs.next()) {
                        return rs.getTimestamp(timestampColumn).getTime();
                    } else {
                        Runtime.error("DataSourceResourceLoader Error: while " + i_operation
                                + " could not find resource " + name);
                    }
                } finally {
                    rs.close();
                }
            } finally {
                closeDbConnection(conn);
            }
        } catch (Exception e) {
            Runtime.error("DataSourceResourceLoader Error: error while " + i_operation
                    + " when trying to load resource " + name + ": " + e.toString());
        }
        return 0;
    }

    /**
     *   gets connection to the datasource specified through the configuration
     *  parameters.
     *
     *  @return connection
     */
    private Connection openDbConnection() throws Exception {
        if (ctx == null) {
            ctx = new InitialContext();
        }

        if (dataSource == null) {
            dataSource = (DataSource) ctx.lookup(dataSourceName);
        }

        return dataSource.getConnection();
    }

    /**
     *  Closes connection to the datasource
     */
    private void closeDbConnection(Connection conn) {
        try {
            conn.close();
        } catch (Exception e) {
            Runtime.info("DataSourceResourceLoader Quirk: problem when closing connection: " + e.toString());
        }
    }

    /**
     *  Reads the data from the datasource.  It simply does the following query :
     *  <br>
     *   SELECT <i>columnNames</i> FROM <i>tableName</i> WHERE <i>keyColumn</i>
     *      = '<i>templateName</i>'
     *  <br>
     *  where <i>keyColumn</i> is a class member set in init()
     *
     *  @param conn connection to datasource
     *  @param columnNames columns to fetch from datasource
     *  @param templateName name of template to fetch
     *  @return result set from query
     */
    private ResultSet readData(Connection conn, String columnNames, String templateName) throws SQLException {
        Statement stmt = conn.createStatement();

        String sql = "SELECT " + columnNames + " FROM " + tableName + " WHERE " + keyColumn + " = '" + templateName
                + "'";

        return stmt.executeQuery(sql);
    }
}