trunk/com/so/news/storage/Database.java
author chris <chris@marvin>
Tue Jan 20 10:21:03 2009 +0100 (2009-01-20)
changeset 0 f907866f0e4b
permissions -rw-r--r--
Initial import.
     1 /*
     2  *   StarOffice News Server
     3  *   see AUTHORS for the list of contributors
     4  *
     5  *   This program is free software: you can redistribute it and/or modify
     6  *   it under the terms of the GNU General Public License as published by
     7  *   the Free Software Foundation, either version 3 of the License, or
     8  *   (at your option) any later version.
     9  *
    10  *   This program is distributed in the hope that it will be useful,
    11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  *   GNU General Public License for more details.
    14  *
    15  *   You should have received a copy of the GNU General Public License
    16  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  */
    18 
    19 package com.so.news.storage;
    20 
    21 import java.sql.Connection;
    22 import java.sql.DriverManager;
    23 import java.sql.ResultSet;
    24 import java.sql.SQLException;
    25 import java.sql.Statement;
    26 
    27 import java.util.zip.CRC32;
    28 import com.so.news.Config;
    29 import com.so.news.util.StringTemplate;
    30 
    31 /**
    32  * Database abstraction class.
    33  * @author Christian Lins (christian.lins@web.de)
    34  */
    35 public class Database
    36 {
    37   private static Database instance = null;
    38   
    39   /**
    40    * Initializes the Database subsystem, e.g. loading a JDBC driver and
    41    * connection to the Database Managment System.
    42    * This method is called when the daemon starts up or at the first
    43    * call to Database.getInstance().
    44    * @throws java.lang.Exception
    45    */
    46   public static void arise()
    47     throws Exception
    48   {
    49     // Tries to load the Database driver and establish a connection.
    50     if(instance == null)
    51       instance = new Database();
    52   }
    53   
    54   /**
    55    * @return Instance of the current Database backend. Returns null if an error
    56    * has occurred.
    57    */
    58   public static Database getInstance()
    59   {
    60     try
    61     {
    62       arise();
    63       return instance;
    64     }
    65     catch(Exception ex)
    66     {
    67       ex.printStackTrace();
    68       return null;
    69     }
    70   }
    71   
    72   private Connection conn = null;
    73   
    74   /**
    75    * Private constructor.
    76    * @throws java.lang.Exception
    77    */
    78   private Database()
    79     throws Exception
    80   {
    81     Class.forName(
    82             Config.getInstance().get("n3tpd.storage.dbmsdriver", ""));
    83     this.conn = DriverManager.getConnection(
    84             Config.getInstance().get("n3tpd.storage.database", ""),
    85             Config.getInstance().get("n3tpd.storage.user", "n3tpd_user"),
    86             Config.getInstance().get("n3tpd.storage.password", ""));
    87     this.conn.setAutoCommit(false);
    88   }
    89   
    90   /**
    91    * Adds an article to the database.
    92    * @param article
    93    * @return
    94    * @throws java.sql.SQLException
    95    */
    96   public boolean addArticle(Article article)
    97     throws SQLException
    98   {
    99     Statement stmt = this.conn.createStatement();
   100 
   101     String sql0 = "START TRANSACTION";
   102     String sql1 = "INSERT INTO articles (message_id,header,body)" +
   103             "VALUES('%mid', '%header', '%body')";
   104     StringTemplate tmpl = new StringTemplate(sql1);
   105     tmpl.set("body", article.getBody());
   106     tmpl.set("mid", article.getMessageID());
   107     tmpl.set("header", article.getHeaderSource());
   108     sql1 = tmpl.toString();
   109     
   110     String sql2 = "COMMIT";
   111     
   112     // Add statements as batch
   113     stmt.addBatch(sql0);
   114     stmt.addBatch(sql1);
   115     
   116     // TODO: For each newsgroup add a reference
   117     String sql = "INSERT INTO postings (group_id, article_id, article_index)" +
   118                  "VALUES (%gid, (SELECT article_id FROM articles WHERE message_id = '%mid')," +
   119                  " %idx)";
   120     
   121     tmpl = new StringTemplate(sql);
   122     tmpl.set("gid", article.getGroupID());
   123     tmpl.set("mid", article.getMessageID());
   124     tmpl.set("idx", getMaxArticleIndex() + 1);
   125     stmt.addBatch(tmpl.toString());
   126     
   127     // Commit
   128     stmt.addBatch(sql2);
   129     
   130     // And execute the batch
   131     stmt.executeBatch();
   132     
   133     return true;
   134   }
   135   
   136   /**
   137    * Adds a group to the Database.
   138    * @param name
   139    * @throws java.sql.SQLException
   140    */
   141   public boolean addGroup(String name)
   142     throws SQLException
   143   {
   144     CRC32 crc = new CRC32();
   145     crc.update(name.getBytes());
   146     
   147     long id = crc.getValue();
   148     
   149     Statement stmt = conn.createStatement();
   150     return 1 == stmt.executeUpdate("INSERT INTO Groups (ID, Name) VALUES (" + id + ", '" + name + "')");
   151   }
   152   
   153   public void delete(Article article)
   154   {
   155     
   156   }
   157   
   158   public void delete(Group group)
   159   {
   160     
   161   }
   162   
   163   public Article getArticle(String messageID)
   164     throws SQLException
   165   {
   166     Statement stmt = this.conn.createStatement();
   167     ResultSet rs =
   168       stmt.executeQuery("SELECT * FROM articles WHERE message_id = '" + messageID + "'");
   169     
   170     return new Article(rs);
   171   }
   172   
   173   public Article getArticle(long gid, long article_id)
   174     throws SQLException
   175   {
   176     Statement stmt = this.conn.createStatement();
   177     String sql = "SELECT * FROM articles WHERE article_id = " +
   178             "(SELECT article_id FROM postings WHERE " +
   179             "group_id = " + gid + " AND article_id = " + article_id +")";
   180     ResultSet rs =
   181       stmt.executeQuery(sql);
   182     
   183     if(rs.next())
   184       return new Article(rs);
   185     else
   186       return null;
   187   }
   188   
   189   public ResultSet getArticles()
   190     throws SQLException
   191   {
   192     Statement stmt = conn.createStatement();
   193     return stmt.executeQuery("SELECT * FROM articles");
   194   }
   195   
   196   /**
   197    * Reads all Groups from the Database.
   198    * @return
   199    * @throws java.sql.SQLException
   200    */
   201   public ResultSet getGroups()
   202     throws SQLException
   203   {
   204     Statement stmt = conn.createStatement();
   205     ResultSet rs = stmt.executeQuery("SELECT * FROM groups");
   206     
   207     return rs;
   208   }
   209   
   210   /**
   211    * Returns the Group that is identified by the name.
   212    * @param name
   213    * @return
   214    * @throws java.sql.SQLException
   215    */
   216   public Group getGroup(String name)
   217     throws SQLException
   218   {   
   219     Statement stmt = this.conn.createStatement();
   220     String sql = "SELECT group_id FROM groups WHERE Name = '%name'";
   221     StringTemplate tmpl = new StringTemplate(sql);
   222     tmpl.set("name", name);
   223     
   224     ResultSet rs = stmt.executeQuery(tmpl.toString());
   225   
   226     if(!rs.next())
   227       return null;
   228     else
   229     {
   230       long id = rs.getLong("group_id");
   231       return new Group(name, id);
   232     }
   233   }
   234   
   235   public int getMaxArticleIndex()
   236     throws SQLException
   237   {
   238     Statement stmt = conn.createStatement();
   239     ResultSet rs = stmt.executeQuery(
   240       "SELECT Max(article_index) FROM postings");
   241     
   242     if(!rs.next())
   243       return 0;
   244     else
   245       return rs.getInt(1);
   246   }
   247   
   248   public int getLastArticleNumber(Group group)
   249     throws SQLException
   250   {
   251     Statement stmt = conn.createStatement();
   252     ResultSet rs = stmt.executeQuery(
   253       "SELECT Max(article_index) FROM postings WHERE group_id = " + group.getID());
   254     
   255     if(!rs.next())
   256       return 0;
   257     else
   258       return rs.getInt(1);
   259   }
   260   
   261   public int getFirstArticleNumber(Group group)
   262     throws SQLException
   263   {
   264     Statement stmt = conn.createStatement();
   265     ResultSet rs = stmt.executeQuery(
   266       "SELECT Min(article_index) FROM postings WHERE group_id = " + group.getID());
   267   
   268     if(!rs.next())
   269       return 0;
   270     else
   271       return rs.getInt(1);
   272   }
   273   
   274   /**
   275    * Returns a group name identified by the given id.
   276    * @param id
   277    * @return
   278    * @throws java.sql.SQLException
   279    */
   280   public String getGroup(int id)
   281     throws SQLException
   282   {
   283     Statement stmt = conn.createStatement();
   284     ResultSet rs   = stmt.executeQuery(
   285             "SELECT name FROM groups WHERE group_id = '" + id + "'");
   286     
   287     if(rs.next())
   288     {
   289       return rs.getString(1);
   290     }
   291     else
   292       return null;
   293   }
   294   
   295   public Article getOldestArticle()
   296     throws SQLException
   297   {
   298     Statement stmt = conn.createStatement();
   299     ResultSet rs = 
   300       stmt.executeQuery("SELECT * FROM Articles WHERE Date = (SELECT Min(Date) FROM Articles)");
   301     
   302     if(rs.next())
   303       return new Article(rs);
   304     else
   305       return null;
   306   }
   307   
   308   /**
   309    * Checks if there is a group with the given name in the Database.
   310    * @param name
   311    * @return
   312    * @throws java.sql.SQLException
   313    */
   314   public boolean isGroupExisting(String name)
   315     throws SQLException
   316   {
   317     Statement stmt = this.conn.createStatement();
   318     ResultSet rs   = stmt.executeQuery("SELECT * FROM Groups WHERE Name = '" + name + "'");
   319     
   320     return rs.next();
   321   }
   322   
   323   public void updateArticle(Article article)
   324   {
   325     
   326   }
   327 }