DatabaseConnection.java
上传用户:psq1974
上传日期:2007-01-06
资源大小:1195k
文件大小:18k
- /* Copyright (C) 1998, 1999 State University of New York at Stony Brook
- Author: Andrew V. Shuvalov ( andrew@ecsl.cs.sunysb.edu )
- Software license is located in file "COPYING"
- VideoServer application
- $Id: DatabaseConnection.java,v 1.21 1999/03/13 03:06:34 andrew Exp $
- */
- package edu.sunysb.cs.ecsl.videoserver;
- import java.io.*;
- import java.net.*;
- import java.sql.*;
- import java.text.*;
- import java.util.Vector;
- import java.util.Calendar;
- import java.util.Date;
- /** interface with database
- */
- class DatabaseConnection implements TextProtocol {
- VSProperties props = null;
- Connection dbConnection = null;
- /** class to operate the database as a whole */
- DatabaseMetaData dbmd = null;
- /** this name is set first to default, next can be modified
- */
- protected String currentDatabaseName = null;
-
- /** parent thread */
- VideoServerThread parent_thread;
- protected VideoServer application = null;
- /** formatter for date/time for all functions */
- SimpleDateFormat dateFormat;
- protected DatabaseConnection( VideoServerThread vst,
- VideoServer appl,
- DataOutputStream outputStream )
- throws IOException, SQLException {
- parent_thread = vst;
- application = appl;
- props = VSProperties.GetPropertiesInstance();
- dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss zzz");
- try {
- connect( props.getProperty( props.DatabaseName ) );
- } catch ( ClassNotFoundException e ) {
- throw new SQLException( e.toString() );
- }
- }
- protected void connect( String dbname )
- throws SQLException, ClassNotFoundException {
- currentDatabaseName = new String( dbname );
- String db = new String( props.getProperty( props.DatabaseEngine )
- + ":" + dbname );
-
- // --- Load the driver
- try
- {
- Class.forName( props.getProperty(props.DatabaseEngineClassName));
- } catch (ClassNotFoundException e) {
- System.err.println("Exception: " + e.toString());
- parent_thread.debug_forced("Exception: " + e.toString());
- throw new ClassNotFoundException( e.toString() );
- }
- if( dbConnection != null )
- {
- dbConnection.close();
- dbmd = null;
- }
- dbConnection = DriverManager.getConnection
- ( db, props.getProperty( props.DatabaseUserName ), "" );
- dbmd = dbConnection.getMetaData();
- parent_thread.debug( "connected to the database " + dbname, 1 );
- }
- /** the hole database entities format is hard-coded here. I see no reason
- to put this is some kind of configuration
- */
- private void create_new_database()
- throws SQLException, ClassNotFoundException {
- if( dbConnection == null )
- return;
-
- parent_thread.debug_forced("Creating new database "+currentDatabaseName);
- Statement s;
- try {
- s = dbConnection.createStatement();
- s.execute( "DROP TABLE moviefiles, movies, captions" );
- s.close();
- } catch( SQLException e ) {
- // that's ok, that means nothing to drop
- }
-
- s = dbConnection.createStatement();
- s.execute( "CREATE TABLE moviefiles ( " +
- // -- uniqely generated from title
- // -- it may be several moviefiles with this id
- "id int, " +
- // -- uniqely identify the push server which holds this movie
- "pushserv_id int, " +
- // -- store the relative path of file, not from root
- "mpegfile varchar(255), " +
- "starttm timestamp, " +
- "stoptm timestamp " +
- ") " );
- s.close();
-
- s = dbConnection.createStatement();
- s.execute( "CREATE TABLE movies ( " +
- // -- Title must be unique
- "title varchar(100), " +
- // -- uniqely generated from title and used
- // -- in moviefile
- "id int, " +
- // -- comments
- "description text, " +
- "starttm timestamp, " +
- "stoptm timestamp )" );
- s.close();
- s = dbConnection.createStatement();
- s.execute( "CREATE TABLE captions ( " +
- // -- movie id
- "id int, " +
- "text varchar(255), " +
- "captime timestamp )" );
- s.close();
- }
- protected void finalize() throws Throwable {
- dbConnection.close();
- }
- /** set or ask database name
- */
- protected void database_impl( Vector args, BufferedReader inputReader,
- DataOutputStream outputStream,
- boolean SuperuserStatus )
- throws SyntaxException, SQLException, IOException {
- if( dbConnection == null )
- {
- parent_thread.debug_forced( "!Not connected" );
- outputStream.writeBytes( "->n" + _disconnect_[KEY] + "n<-n" );
- return;
- }
- // ask the currently connected database name
- if( args.size() == 1 ) {
- outputStream.writeBytes( "->n" + currentDatabaseName + "n<-n" );
- }
- else if( args.size() == 2 ) {
- application.log( 1, "connecting to another database " +
- args.elementAt( 1 ) );
- try {
- connect( ((String)args.elementAt( 1 )).trim() );
- outputStream.writeBytes( "->n"+currentDatabaseName+"n<-n" );
- application.log( 2, "connected" );
- } catch( SQLException e ) {
- application.log( 1, e.toString() );
- parent_thread.debug_forced( e.toString() );
- outputStream.writeBytes( "->n" + _disconnect_[KEY] +
- "n<-n" );
- return;
- } catch ( ClassNotFoundException e ) {
- // that's fatal
- application.log( 1, e.toString() );
- parent_thread.debug_forced( e.toString() );
- outputStream.writeBytes( "->n" + _disconnect_[KEY] +
- "n<-n" );
- return;
- }
- }
- else
- throw new SyntaxException
- (_database_name_[KEY]+" command accepts only 0 or 1 parameters");
- // test if this database is initialised. If not - do it.
- try {
- Statement s;
- ResultSet rs;
- s = dbConnection.createStatement();
- rs = s.executeQuery("select * from movies");
- s.close();
- } catch( SQLException e ) {
- if( SuperuserStatus ) {
- // superuser have the right to create the new database
- try {
- create_new_database();
- } catch( Exception ex ) {
- // any
- application.log( 1, ex.toString() );
- parent_thread.debug_forced( ex.toString() );
- outputStream.writeBytes( "->n" + _disconnect_[KEY] +
- "n<-n" );
- }
- }
- else {
- // there is nothing i can do
- application.log( 1, "only superuser may " +
- "initialize new database" );
- parent_thread.debug_forced( "only superuser may " +
- "initialize new database" );
- outputStream.writeBytes( "->n" + _disconnect_[KEY] +
- "n<-n" );
- return;
- }
- }
- }
- /** list movies in database */
- protected void listmovies_impl( Vector args, BufferedReader inputReader,
- DataOutputStream outputStream,
- boolean SuperuserStatus )
- throws SyntaxException, SQLException, IOException {
- if( dbConnection == null )
- {
- parent_thread.debug_forced("!Not connectedn");
- outputStream.writeBytes( "->n" + _disconnect_[KEY] + "n<-n" );
- return;
- }
-
- try {
- Statement s;
- ResultSet rs;
- s = dbConnection.createStatement();
- rs = s.executeQuery("select title, id, description, " +
- "starttm, stoptm from movies");
- outputStream.writeBytes( "->n" );
- if( rs == null )
- throw new SQLException( "got null in reply to execute query" );
-
- while( rs.next() ) {
- String title = rs.getString( "title" );
- int id = rs.getInt( "id" );
- String comments = rs.getString( "description" );
- // it may be null !
- // comments may have 0 or several lines of text,
- // so first transfer the line count
- Vector comm_lines = new Vector();
- if( comments != null )
- {
- int pos = 0;
- int pos_end = 0;
- while( true )
- {
- pos_end = comments.indexOf( 'n', pos );
- if( pos_end == -1 )
- {
- String line = comments.substring( pos );
- comm_lines.addElement( line );
- break;
- }
- else
- {
- String line = comments.substring( pos, pos_end );
- comm_lines.addElement( line );
- pos = pos_end;
- }
- }
- }
- Date time1stamp = rs.getTimestamp( "starttm" );
- Date time2stamp = rs.getTimestamp( "stoptm" );
- if( time2stamp == null )
- {
- application.log( 3, "unfinished movie #" + String.valueOf( id ));
- time2stamp = Calendar.getInstance().getTime();
- }
- outputStream.writeBytes( title + "n" + id + "n" );
- outputStream.writeBytes( comm_lines.size() + "n" );
- for( int i = 0; i < comm_lines.size(); i++ )
- outputStream.writeBytes( comm_lines.elementAt(i) + "n" );
-
- outputStream.writeBytes( dateFormat.format( time1stamp ) + "n" +
- dateFormat.format( time2stamp ) + "n" );
- s.close();
- }
- } catch (StringIndexOutOfBoundsException e) {
- // i got it once in JDBC driver
- parent_thread.debug_forced( "!" + e.toString() );
- }
- outputStream.writeBytes( "<-n" );
- }
- /** list mov files. We may have several push servers to store the same movie
- - in this case the client should decide himself what push server is
- the nearest and is best to play this movie
- */
- protected void listmovfiles_impl( Vector args, BufferedReader inputReader,
- DataOutputStream outputStream,
- boolean SuperuserStatus )
- throws SyntaxException, SQLException, IOException {
- if( dbConnection == null )
- {
- parent_thread.debug_forced("!Not connectedn");
- outputStream.writeBytes( "->n" + _disconnect_[KEY] + "n<-n" );
- return;
- }
-
- // second argument must be 'id'
- if( args.size() != 2 )
- throw new SyntaxException( _list_mov_files_[KEY] +
- " command accepts exactly" +
- " 1 parameter - integer ID of movie" );
- int id = Integer.parseInt( (String)args.elementAt(1) );
- Statement s;
- ResultSet rs;
- s = dbConnection.createStatement();
- rs = s.executeQuery
- ("select mpegfile, pushserv_id, starttm, stoptm " +
- "from moviefiles f where f.id = " + id);
- outputStream.writeBytes( "->n" );
- while( rs.next() ) {
- String mpegf = rs.getString( "mpegfile" );
- String pushserv_id = rs.getString( "pushserv_id" );
- // the client is not interested what id this push server have
- // client wants IP address and port number
- String ip_addr = props.getProperty
- ( props.PushServN_IP + pushserv_id );
- String control_port = props.getProperty
- ( props.PushServN_Control + pushserv_id );
- String base = props.getProperty( props.PushServN_PPrefix + pushserv_id );
- mpegf = base + "/" + mpegf;
- Date start = rs.getTimestamp( "starttm" );
- Date stop = rs.getTimestamp( "stoptm" );
- if( stop == null )
- {
- application.log( 0, "unfinished file in movie #" +
- String.valueOf( id ));
- stop = Calendar.getInstance().getTime();
- }
- outputStream.writeBytes( mpegf + "n" + pushserv_id + "n" +
- ip_addr + "n" + control_port + "n" +
- dateFormat.format( start ) +
- "n" + dateFormat.format( stop ) + "n" );
- }
- outputStream.writeBytes( "<-n" );
- s.close();
- }
-
- /* list captions. specify id and optionally listing type
- */
- protected void list_captions( Vector args, BufferedReader inputReader,
- DataOutputStream outputStream,
- boolean SuperuserStatus )
- throws SyntaxException, SQLException, IOException {
- if( dbConnection == null )
- {
- parent_thread.debug_forced("!Not connectedn");
- outputStream.writeBytes( "->n" + _disconnect_[KEY] + "n<-n" );
- return;
- }
-
- if( args.size() < 2 )
- throw new SyntaxException( _list_captions_[KEY] + " " +
- _list_captions_[SHDESC] );
- int id;
- try {
- id = Integer.parseInt( (String)args.elementAt(1) );
- } catch ( NumberFormatException e ) {
- throw new SyntaxException( _list_captions_[KEY] + " " +
- _list_captions_[SHDESC] +" "+e.toString());
- }
- Statement s;
- ResultSet rs;
- s = dbConnection.createStatement();
- rs = s.executeQuery
- ("select text, captime from captions c where c.id = "+id);
- outputStream.writeBytes( "->n" );
- while( rs.next() ) {
- String cap = rs.getString( "text" );
- java.util.Date time = rs.getTimestamp( "captime" );
- outputStream.writeBytes( cap + "n" + dateFormat.format( time )+"n");
- }
- outputStream.writeBytes( "<-n" );
- s.close();
- }
- /* add new movie to database. Returns automatically generated ID.
- stopTime may be null - we may not know the time when movie will ends
- */
- protected int add_new_movie( String movieName, Calendar startTime,
- Calendar stopTime )
- throws SyntaxException, SQLException, IOException {
- String start = dateFormat.format( startTime.getTime() );
- String stop = null;
- if( stopTime != null )
- stop = dateFormat.format( stopTime.getTime() );
- return add_new_movie( movieName, start, stop );
- }
- /* add new movie to database. Returns automatically generated ID.
- stopTime may be null - we may not know the time when movie will ends
- */
- protected int add_new_movie( String movieName, String startTime,
- String stopTime )
- throws SyntaxException, SQLException, IOException {
- if( dbConnection == null )
- {
- parent_thread.debug_forced("!Not connectedn");
- return 0;
- }
- Statement s = dbConnection.createStatement();
- ResultSet rs;
- // if exist - don't overwrite
- try {
- int i_postfix = 0;
- // generate the unique name for the movie
- while( true )
- {
- String postfix = "";
- if( i_postfix > 0 )
- postfix = ", part " + String.valueOf( i_postfix );
- rs = s.executeQuery
- ("select title from movies m where m.title = '"
- + movieName + postfix + "'" );
- if( rs.next() ) // found
- {
- i_postfix = i_postfix + 1;
- continue;
- }
- movieName = movieName + postfix;
- break;
- }
- } catch ( SQLException e ) {
- parent_thread.debug( "movie doesn't exists" + e.toString() );
- }
- s.close();
- s = dbConnection.createStatement();
-
- // search for a first free ID
- int id = 1;
- // for( id = 1; ; id++ ) {
- // try {
- // rs = s.executeQuery
- // ( "select m.id from movies m where m.id = " + String.valueOf( id ));
- // } catch ( SQLException e ) {
- // break; // exit from loop, we just found new id
- // }
- // if( !rs.next() ) // found
- // break;
- // }
- try {
- rs = s.executeQuery
- ( "select max( m.id ) + 1 as id from movies m" );
- if( rs.next() )
- id = rs.getInt( "id" );
- } catch ( SQLException e ) {
- // that's ok
- application.log( 3, e.toString() );
- }
- parent_thread.debug( "free id " + String.valueOf( id ) );
- s.close();
- s = dbConnection.createStatement();
- if( stopTime != null )
- s.executeUpdate
- ( "insert into movies (title, id, starttm, stoptm) values ('" +
- movieName + "'," + String.valueOf( id ) + ",'" +
- startTime + "','" + stopTime +
- "')" );
- else
- s.executeUpdate
- ( "insert into movies (title, id, starttm) values ('" +
- movieName + "'," + String.valueOf( id ) + ",'" +
- startTime + "') " );
- s.close();
- return id;
- }
-
- /** add files to movie. stop time may be null if we don't know when this
- movie file will ends
- */
- protected void add_movie_file( String mov_id, String pushserv_id,
- String mpegName, Calendar startTime,
- Calendar stopTime )
- throws SyntaxException, SQLException, IOException {
- String start = dateFormat.format( startTime.getTime() );
- String stop = null;
- if( stopTime != null )
- stop = dateFormat.format( stopTime.getTime() );
- add_movie_file( mov_id, pushserv_id, mpegName, start, stop );
- }
- /** add files to movie. stop time may be null if we don't know when this
- movie file will ends
- */
- protected void add_movie_file( String mov_id, String pushserv_id,
- String mpegName, String startTime,
- String stopTime )
- throws SyntaxException, SQLException, IOException {
- if( dbConnection == null )
- {
- parent_thread.debug_forced("!Not connectedn");
- return;
- }
- Statement s = dbConnection.createStatement();
- ResultSet rs;
- // if exist - don't overwrite
- try {
- rs = s.executeQuery
- ( "select mpegfile from moviefiles m where m.id = " + mov_id +
- " and m.mpegfile = '" + mpegName + "'" );
- if( rs.next() ) // found
- return;
- } catch ( SQLException e ) {
- parent_thread.debug( "select mpegfile from moviefiles m where m.id = " +
- mov_id + " and m.mpegfile = '" + mpegName + "'" );
- parent_thread.debug( "continue with " + e.toString() );
- }
-
- // insert
- if( stopTime != null )
- s.executeUpdate
- ( "insert into moviefiles(id, pushserv_id, mpegfile, starttm, " +
- " stoptm)" +
- " values (" + mov_id + ",'" + pushserv_id + "','" +
- mpegName + "','" + startTime + "','" + stopTime + "')" );
- else
- s.executeUpdate
- ( "insert into moviefiles (id, pushserv_id, mpegfile, starttm)" +
- " values (" + mov_id + ",'" + pushserv_id + "','" +
- mpegName + "','" + startTime + "' )" );
- s.close();
- }
- protected void mark_movie_stop_time( int movie_id )
- throws SyntaxException, SQLException, IOException {
- if( dbConnection == null )
- {
- parent_thread.debug_forced("!Not connectedn");
- return;
- }
- // current time
- String current_time = dateFormat.format(Calendar.getInstance().getTime());
- Statement s = dbConnection.createStatement();
- ResultSet rs;
- // first set this time as stop for specified movie
- s.executeUpdate
- ( "update movies set stoptm = '" + current_time + "' where " +
- "id = " + String.valueOf( movie_id ) );
- // second find the unfinished moviefile for that movie
- // Note: at that point the movie may have only a single moviefiles
- // multiple moviefiles may be created only via 'append'
- s.executeUpdate
- ( "update moviefiles set stoptm = '" + current_time + "' where " +
- "id = " + String.valueOf( movie_id ) );
- }
- protected void add_caption( String id, String time, String text )
- throws SyntaxException, SQLException, IOException {
- if( dbConnection == null )
- {
- parent_thread.debug_forced("!Not connectedn");
- return;
- }
- Statement s = dbConnection.createStatement();
- ResultSet rs;
-
- // text may have chars, that must be quoted...
- int idx = 0;
- while( -1 != ( idx = text.indexOf( "'", idx ))) {
- text = text.substring( 0, idx ) + "'" + text.substring( idx );
- idx += 2;
- if( idx >= text.length())
- break;
- }
-
- // insert
- s.executeUpdate
- ( "insert into captions (id, text, captime) values (" +
- id + ",'" + text + "','" + time + "')" );
- s.close();
- }
- }