org.danann.cernunnos.sql.OpenConnectionTask.java Source code

Java tutorial

Introduction

Here is the source code for org.danann.cernunnos.sql.OpenConnectionTask.java

Source

/*
 * Copyright 2007 Andrew Wills
 *
 * 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.danann.cernunnos.sql;

import java.sql.Connection;

import javax.sql.DataSource;

import org.danann.cernunnos.AbstractContainerTask;
import org.danann.cernunnos.AttributePhrase;
import org.danann.cernunnos.EntityConfig;
import org.danann.cernunnos.Formula;
import org.danann.cernunnos.LiteralPhrase;
import org.danann.cernunnos.Phrase;
import org.danann.cernunnos.Reagent;
import org.danann.cernunnos.ReagentType;
import org.danann.cernunnos.SimpleFormula;
import org.danann.cernunnos.SimpleReagent;
import org.danann.cernunnos.TaskRequest;
import org.danann.cernunnos.TaskResponse;
import org.springframework.jdbc.datasource.DataSourceUtils;

/**
 * <code>Task</code> implementation that opens a JDBC connection and makes it
 * available to subtasks.  The new connection will automatically be closed when
 * execution of this task concludes.
 */
@Deprecated
public final class OpenConnectionTask extends AbstractContainerTask {

    // Instance Members.
    private Phrase attribute_name;
    private Phrase data_source;

    private Phrase driverPhrase;
    private Phrase urlPhrase;
    private Phrase usernamePhrase;
    private Phrase passwordPhrase;
    private BasicDataSourceTemplate basicDataSourceTemplate;

    /*
     * Public API.
     */

    public static final Reagent ATTRIBUTE_NAME = new SimpleReagent("ATTRIBUTE_NAME", "@attribute-name",
            ReagentType.PHRASE, String.class,
            "Optional name under which the new connection will be registered as a request attribute.  If omitted, "
                    + "the name 'SqlAttributes.CONNECTION' will be used.",
            new LiteralPhrase(SqlAttributes.CONNECTION));

    public static final Reagent DATA_SOURCE = new SimpleReagent("DATA_SOURCE", "@data-source", ReagentType.PHRASE,
            DataSource.class,
            "Optional DataSource object from which the connection may be opened.  This phrase will be evaluated only if "
                    + "DRIVER, URL, USERNAME, and PASSWORD are not provided.  The default is a request attribute under the name "
                    + "'SqlAttributes.DATA_SOURCE'.",
            new AttributePhrase(SqlAttributes.DATA_SOURCE));

    public static final Reagent DATA_SOURCE_ATTRIBUTE_NAME = new SimpleReagent("DATA_SOURCE_ATTRIBUTE_NAME",
            "@data-source-attribute-name", ReagentType.PHRASE, String.class,
            "Optional name under which the new DataSource will be registered as a request attribute.  If omitted, "
                    + "the name 'SqlAttributes.DATA_SOURCE' will be used.",
            new LiteralPhrase(SqlAttributes.DATA_SOURCE));

    public static final Reagent DRIVER = new SimpleReagent("DRIVER", "@driver", ReagentType.PHRASE, String.class,
            "Optional JDBC driver class name to use when opening the connection.  You must "
                    + "provide either DATA_SOURCE or DRIVER, URL, USERNAME, and PASSWORD.",
            null);

    public static final Reagent URL = new SimpleReagent("URL", "@url", ReagentType.PHRASE, String.class,
            "Optional JDBC connection URL to use when opening the connection.  You "
                    + "must provide either DATA_SOURCE or DRIVER, URL, USERNAME, and PASSWORD.",
            null);

    public static final Reagent USERNAME = new SimpleReagent("USERNAME", "@username", ReagentType.PHRASE,
            String.class, "Optional username to use when opening the connection.  You must provide either "
                    + "DATA_SOURCE or DRIVER, URL, USERNAME, and PASSWORD.",
            null);

    public static final Reagent PASSWORD = new SimpleReagent("PASSWORD", "@password", ReagentType.PHRASE,
            String.class, "Optional password to use when opening the connection.  You must provide either "
                    + "DATA_SOURCE or DRIVER, URL, USERNAME, and PASSWORD.",
            null);

    public Formula getFormula() {
        Reagent[] reagents = new Reagent[] { ATTRIBUTE_NAME, DATA_SOURCE, DRIVER, URL, USERNAME, PASSWORD,
                DATA_SOURCE_ATTRIBUTE_NAME, AbstractContainerTask.SUBTASKS };
        return new SimpleFormula(getClass(), reagents);
    }

    @Override
    public void init(EntityConfig config) {
        super.init(config);

        // Instance Members.
        this.attribute_name = (Phrase) config.getValue(ATTRIBUTE_NAME);
        this.data_source = (Phrase) config.getValue(DATA_SOURCE);

        final Phrase dataSourceAttributeName = (Phrase) config.getValue(DATA_SOURCE_ATTRIBUTE_NAME);
        this.driverPhrase = (Phrase) config.getValue(DRIVER);
        this.urlPhrase = (Phrase) config.getValue(URL);
        this.usernamePhrase = (Phrase) config.getValue(USERNAME);
        this.passwordPhrase = (Phrase) config.getValue(PASSWORD);
        this.basicDataSourceTemplate = new BasicDataSourceTemplateImpl(dataSourceAttributeName, driverPhrase,
                urlPhrase, usernamePhrase, passwordPhrase);
    }

    public void perform(TaskRequest req, TaskResponse res) {
        final DataSource dataSource;
        if (this.driverPhrase != null && this.urlPhrase != null && this.usernamePhrase != null
                && this.passwordPhrase != null) {
            //Use the BasicDataSource template to create and bind the DataSource then call performCreateConnection
            this.basicDataSourceTemplate.perform(req, res);
        } else {
            //Use the existing DataSource to call performCreateConnection
            dataSource = (DataSource) data_source.evaluate(req, res);
            this.performCreateConnection(req, res, dataSource);
        }
    }

    protected void performCreateConnection(TaskRequest req, TaskResponse res, DataSource dataSource) {
        final Connection connection = DataSourceUtils.getConnection(dataSource);
        try {
            // Make it available as a request attribute...
            final String connectionAttrName = (String) attribute_name.evaluate(req, res);
            res.setAttribute(connectionAttrName, connection);

            // Invoke subtasks...
            super.performSubtasks(req, res);
        } finally {
            DataSourceUtils.releaseConnection(connection, dataSource);
        }
    }

    /**
     * Local DataSource template that executes {@link OpenConnectionTask#performCreateConnection(TaskRequest, TaskResponse, DataSource)}
     * in the call-back.
     */
    private final class BasicDataSourceTemplateImpl extends BasicDataSourceTemplate {
        private BasicDataSourceTemplateImpl(Phrase attributeNamePhrase, Phrase driverPhrase, Phrase urlPhrase,
                Phrase usernamePhrase, Phrase passwordPhrase) {
            super(attributeNamePhrase, driverPhrase, urlPhrase, usernamePhrase, passwordPhrase);
        }

        @Override
        protected void performWithDataSource(TaskRequest req, TaskResponse res, DataSource dataSource) {
            OpenConnectionTask.this.performCreateConnection(req, res, dataSource);
        }
    }
}