001/*
002 * Copyright (c) 2009-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2016-09-14 19:10:43 +0000 (Wed, 14 Sep 2016) $' 
007 * '$Revision: 34528 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.geon;
031
032import java.sql.Connection;
033import java.sql.PreparedStatement;
034import java.sql.SQLException;
035
036import ptolemy.actor.TypedAtomicActor;
037import ptolemy.actor.TypedIOPort;
038import ptolemy.actor.parameters.PortParameter;
039import ptolemy.data.BooleanToken;
040import ptolemy.data.DoubleToken;
041import ptolemy.data.IntToken;
042import ptolemy.data.LongToken;
043import ptolemy.data.RecordToken;
044import ptolemy.data.StringToken;
045import ptolemy.data.Token;
046import ptolemy.data.expr.Parameter;
047import ptolemy.data.type.BaseType;
048import ptolemy.data.type.Type;
049import ptolemy.kernel.CompositeEntity;
050import ptolemy.kernel.util.IllegalActionException;
051import ptolemy.kernel.util.NameDuplicationException;
052
053/**
054 * A base class for actors that access JDBC databases.
055 * 
056 * @author Daniel Crawl
057 * @version $Id: DatabaseAccessor.java 34528 2016-09-14 19:10:43Z crawl $
058 */
059
060public class DatabaseAccessor extends TypedAtomicActor {
061        public DatabaseAccessor(CompositeEntity container, String name)
062                        throws NameDuplicationException, IllegalActionException {
063                super(container, name);
064
065                dbParams = new PortParameter(this, "dbParams");
066                Type type = OpenDBConnection.getDBParamsType();
067                dbParams.setTypeEquals(type);
068                dbParams.getPort().setTypeEquals(type);
069
070                dbcon = new TypedIOPort(this, "dbcon", true, false);
071                dbcon.setTypeEquals(DBConnectionToken.DBCONNECTION);
072
073                dbconTokenConsumptionRate = new Parameter(dbcon,
074                                "tokenConsumptionRate", IntToken.ONE);
075        }
076
077        // /////////////////////////////////////////////////////////////////
078        // // ports and parameters ////
079
080        /** A record token containing parameters to create a database connection. */
081        public PortParameter dbParams;
082
083        /** A reference to the database connection. */
084        public TypedIOPort dbcon;
085
086        /** Parameter to change token consumption rate on dbcon. */
087        public Parameter dbconTokenConsumptionRate;
088
089        // /////////////////////////////////////////////////////////////////
090        // // public methods ////
091
092        /** Close the connection if open. */
093        @Override
094    public void initialize() throws IllegalActionException {
095                super.initialize();
096                _closeConnection();
097        }
098
099        /** If connection is closed, open a new one. */
100        @Override
101    public void fire() throws IllegalActionException {
102            dbParams.update();
103            if (_db == null) {
104                        getConnection();
105                }
106        }
107
108        /** Close the connection if open. */
109        @Override
110    public void wrapup() throws IllegalActionException {
111                super.wrapup();
112                _closeConnection();
113        }
114
115        // /////////////////////////////////////////////////////////////////
116        // // protected methods ////
117
118        /** Get the database connection. */
119        protected void getConnection() throws IllegalActionException {
120                // first check dbParams
121                RecordToken params = (RecordToken) dbParams.getToken();
122                if (params != null) {
123                        _db = OpenDBConnection.getConnection(params);
124                } else if(_db == null && dbcon.getWidth() > 0) {
125                        DBConnectionToken dbToken = (DBConnectionToken) dbcon.get(0);
126                        try {
127                                _db = dbToken.getValue();
128                        } catch (Exception e) {
129                                throw new IllegalActionException(this, e, "CONNECTION FAILURE");
130                        }
131                }
132                
133                if(_db == null) {
134                    throw new IllegalActionException(this, "Must provide either" +
135                        " database connection parameters in dbParams or database" +
136                        " connection in dbcon.");
137                }
138
139                // we no longer need to read from dbcon
140                dbconTokenConsumptionRate.setToken(IntToken.ZERO);
141        }
142        
143           /** Set a parameter value in a prepared statement.
144     *  @param st The prepared statement
145     *  @param index The index to set in the prepared statement
146     *  @param token The token containing the value to set.
147     */
148    protected void _setPreparedStatementValue(PreparedStatement st, int index, Token token) 
149            throws IllegalActionException, SQLException {
150        Type type = token.getType();
151        if(type == BaseType.STRING) {
152            st.setString(index, ((StringToken)token).stringValue());
153        } else if(type == BaseType.INT) {
154            st.setInt(index, ((IntToken)token).intValue());
155        } else if(type == BaseType.LONG) {
156            st.setLong(index, ((LongToken)token).longValue());
157        } else if(type == BaseType.DOUBLE) {
158            st.setDouble(index, ((DoubleToken)token).doubleValue());
159        } else if(type == BaseType.BOOLEAN) {
160            st.setBoolean(index, ((BooleanToken)token).booleanValue());
161        } else {
162            st.setString(index, token.toString());
163        }
164    }
165
166
167        // /////////////////////////////////////////////////////////////////
168        // // protected variables ////
169
170        /** A JDBC database connection. */
171        protected Connection _db = null;
172
173        // /////////////////////////////////////////////////////////////////
174        // // private methods ////
175
176        /** Close the connection if open. */
177        private void _closeConnection() throws IllegalActionException {
178                try {
179                        if (_db != null) {
180                                _db.close();
181                        }
182                        _db = null;
183
184                        // reset the token consumption rate on dbcon
185                        dbconTokenConsumptionRate.setToken(IntToken.ONE);
186                } catch (SQLException e) {
187                        throw new IllegalActionException(this, "SQLException: "
188                                        + e.getMessage());
189                }
190        }
191}