001 /* 002 Copyright (C) 2001-2003 Laurent Martelli <laurent@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public License 015 along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 017 018 package org.objectweb.jac.aspects.persistence; 019 020 import java.sql.Connection; 021 import java.sql.DriverManager; 022 import java.sql.ResultSet; 023 import java.sql.SQLException; 024 import java.util.HashSet; 025 import java.util.Iterator; 026 import java.util.Map.Entry; 027 import java.util.Map; 028 import org.apache.log4j.Logger; 029 import org.objectweb.jac.util.Log; 030 import org.objectweb.jac.util.Strings; 031 032 033 /** 034 * Implements the storage to store within a PostgreSQL database. 035 */ 036 037 public class PostgresStorage extends SQLStorage { 038 static Logger logger = Logger.getLogger("persistence.storage"); 039 040 /** 041 * Creates a new storage for a PostgreSQL database. 042 * 043 * @param database the database. It may take on eof the following form: 044 * <ul> 045 * <li>database</li> 046 * <li>//host/database</li> 047 * <li>//host:port/database</li> 048 * </ul> 049 * @param user the user name 050 * @param password the password for this user 051 */ 052 053 public PostgresStorage(PersistenceAC ac, 054 String database, String user, String password) 055 throws SQLException 056 { 057 super(ac); 058 try { 059 Class.forName("org.postgresql.Driver"); 060 } catch (ClassNotFoundException e) { 061 logger.error("failed to load postgresql JDBC driver : "+e); 062 return; 063 } 064 try { 065 Connection db; 066 db = DriverManager.getConnection("jdbc:postgresql:"+database,user,password); 067 setConnection(db); 068 } catch (SQLException e) { 069 logger.error("failed to connect to the database with "+ 070 "jdbc:postgresql:"+database+","+user+","+password+": "+e); 071 e.printStackTrace(); 072 } 073 } 074 075 public long getNextVal(String sequence) throws Exception { 076 ensureSequenceExists(sequence); 077 return getLong("select nextval('"+sequence+"')"); 078 } 079 080 public long getCurrVal(String sequence) throws Exception { 081 ensureSequenceExists(sequence); 082 return getLong("select last_value from "+sequence); 083 } 084 085 protected boolean ensureSequenceExists(String sequence) throws Exception { 086 boolean created = false; 087 if (!createdSequences.contains(sequence)) { 088 if (!hasSequence(sequence)) { 089 execute("create sequence \""+sequence+"\""); 090 created = true; 091 } 092 createdSequences.add(sequence); 093 } 094 return created; 095 } 096 097 HashSet createdSequences = new HashSet(); 098 public String newName(String className) throws Exception { 099 String prefix = Strings.getShortClassName(className).toLowerCase(); 100 String seq = getClassSeqName(className); 101 return prefix+"#"+(getNextVal(seq)-1); 102 } 103 104 protected String getClassSeqName(String className) { 105 return Strings.getShortClassName(className).toLowerCase()+"_seq"; 106 } 107 108 protected boolean hasTable(String name) throws Exception { 109 ResultSet rs = 110 executeQuery("select * from pg_tables where tablename='"+name+"'"); 111 return rs.next(); 112 } 113 114 protected boolean hasSequence(String name) throws Exception { 115 ResultSet rs = 116 executeQuery("select * from pg_class where relname='"+name+"' and relkind='S'"); 117 return rs.next(); 118 } 119 120 public void updateNameCounters(Map counters) throws Exception { 121 Iterator i = counters.entrySet().iterator(); 122 while (i.hasNext()) { 123 Entry entry = (Entry)i.next(); 124 String sequence = getClassSeqName((String)entry.getKey()); 125 ensureSequenceExists(sequence); 126 if (getCurrVal(sequence)<((Long)entry.getValue()).longValue()) 127 execute("select setval('"+sequence+"',"+entry.getValue()+",false)"); 128 } 129 } 130 131 }