KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > aspects > persistence > PostgresStorage


1 /*
2   Copyright (C) 2001-2003 Laurent Martelli <laurent@aopsys.com>
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2 of the
7   License, or (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   GNU Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

17
18 package org.objectweb.jac.aspects.persistence;
19
20 import java.sql.Connection JavaDoc;
21 import java.sql.DriverManager JavaDoc;
22 import java.sql.ResultSet JavaDoc;
23 import java.sql.SQLException JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Hashtable JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Map.Entry;
28 import java.util.Map JavaDoc;
29 import org.apache.log4j.Level;
30 import org.apache.log4j.Logger;
31 import org.objectweb.jac.util.Log;
32 import org.objectweb.jac.util.Strings;
33
34
35 /**
36  * Implements the storage to store within a PostgreSQL database.
37  */

38
39 public class PostgresStorage extends SQLStorage {
40     static Logger logger = Logger.getLogger("persistence.storage");
41
42     /** Storage version */
43     static final int version = 1;
44
45     /**
46      * Creates a new storage for a PostgreSQL database.
47      *
48      * @param database the database. It may take on eof the following form:
49      * <ul>
50      * <li>database</li>
51      * <li>//host/database</li>
52      * <li>//host:port/database</li>
53      * </ul>
54      * @param user the user name
55      * @param password the password for this user
56      */

57     public PostgresStorage(PersistenceAC ac,
58                            String JavaDoc database, String JavaDoc user, String JavaDoc password)
59         throws SQLException JavaDoc, Exception JavaDoc
60     {
61         super(ac);
62         try {
63             Class.forName("org.postgresql.Driver");
64         } catch (ClassNotFoundException JavaDoc e) {
65             logger.error("failed to load postgresql JDBC driver",e);
66             return;
67         }
68         try {
69             Connection JavaDoc db;
70             db = DriverManager.getConnection("jdbc:postgresql:"+database,user,password);
71             setConnection(db);
72         } catch (SQLException JavaDoc e) {
73             logger.error("failed to connect to the database with "+
74                          "jdbc:postgresql:"+database+","+user+","+password,e);
75             return;
76         }
77
78         try {
79             doUpdates();
80         } catch (Exception JavaDoc e) {
81             logger.error("doUpdates failed on "+database,e);
82         }
83     }
84
85     protected String JavaDoc[] getClassNames() throws Exception JavaDoc {
86         ResultSet JavaDoc rs = executeQuery("SELECT DISTINCT classid FROM classes");
87         HashSet JavaDoc names = new HashSet JavaDoc();
88         while (rs.next()) {
89             names.add(rs.getString("classid"));
90         }
91         return (String JavaDoc[])names.toArray(new String JavaDoc[0]);
92     }
93
94     protected void doUpdates() throws Exception JavaDoc, SQLException JavaDoc {
95         if (!hasTable("storage")) {
96             execute(
97                 "create table \"storage\" ("+
98                 "\"key\" character varying PRIMARY KEY, "+
99                 "\"value\" character varying )");
100         }
101         int currentVersion = getInt("select value from storage where key='version'",0);
102
103         if (currentVersion<=0) {
104             logger.info("Upgrading from version 0");
105             // Update counter names
106
String JavaDoc[] classes = getClassNames();
107             HashSet JavaDoc seqs = new HashSet JavaDoc();
108             for (int i=0; i<classes.length; i++) {
109                 String JavaDoc seq = Strings.getShortClassName(classes[i]).toLowerCase()+"_seq";
110                 if (seqs.contains(seq))
111                     throw new RuntimeException JavaDoc(
112                         "Cannot upgrade storage: two classes have the same seq name '"+seq+"'");
113                 seqs.add(seq);
114             }
115              
116             for (int i=0; i<classes.length; i++) {
117                 String JavaDoc seq = Strings.getShortClassName(classes[i]).toLowerCase()+"_seq";
118                 if (hasSequence(seq)) {
119                     logger.debug("Renaming sequence "+seq+" to "+classes[i]);
120                     executeUpdate("ALTER TABLE "+seq+" RENAME to \""+classes[i]+"\"");
121                 } else {
122                     logger.debug("No such sequence "+seq);
123                 }
124             }
125             
126         }
127
128         if (currentVersion==0)
129             executeUpdate("insert into storage values ('version',"+version+") ");
130         else
131             executeUpdate("update storage set value="+version+" where key='version'");
132     }
133
134     public long getNextVal(String JavaDoc sequence) throws Exception JavaDoc {
135         ensureSequenceExists(sequence);
136         return getLong("select nextval('\""+sequence+"\"')");
137     }
138
139     public long getCurrVal(String JavaDoc sequence) throws Exception JavaDoc {
140         ensureSequenceExists(sequence);
141         return getLong("select last_value from \""+sequence+"\"");
142     }
143
144     protected boolean ensureSequenceExists(String JavaDoc sequence) throws Exception JavaDoc {
145         boolean created = false;
146         if (!createdSequences.contains(sequence)) {
147             if (!hasSequence(sequence)) {
148                 execute("create sequence \""+sequence+"\"");
149                 created = true;
150             }
151             createdSequences.add(sequence);
152         }
153         return created;
154     }
155
156     HashSet JavaDoc createdSequences = new HashSet JavaDoc();
157     public String JavaDoc newName(String JavaDoc className) throws Exception JavaDoc {
158         String JavaDoc prefix = Strings.getShortClassName(className).toLowerCase();
159         String JavaDoc seq = getClassSeqName(className);
160         return prefix+"#"+(getNextVal(seq)-1);
161     }
162
163     public Map JavaDoc getNameCounters() throws Exception JavaDoc {
164         Hashtable JavaDoc counters = new Hashtable JavaDoc();
165         String JavaDoc[] classes = getClassNames();
166         for (int i=0; i<classes.length; i++) {
167             String JavaDoc seq = getClassSeqName(classes[i]);
168             counters.put(classes[i],new Long JavaDoc(getCurrVal(seq)));
169         }
170
171         return counters;
172     }
173
174     protected String JavaDoc getClassSeqName(String JavaDoc className) {
175         return className;
176     }
177
178     protected boolean hasTable(String JavaDoc name) throws SQLException JavaDoc {
179         ResultSet JavaDoc rs =
180             executeQuery("select * from pg_tables where tablename='"+name+"'");
181         return rs.next();
182     }
183
184     protected boolean hasSequence(String JavaDoc name) throws Exception JavaDoc {
185         ResultSet JavaDoc rs =
186             executeQuery("select * from pg_class where relname='"+name+"' and relkind='S'");
187         return rs.next();
188     }
189
190     public void updateNameCounters(Map JavaDoc counters) throws Exception JavaDoc {
191         Iterator JavaDoc i = counters.entrySet().iterator();
192         while (i.hasNext()) {
193             Entry entry = (Entry)i.next();
194             String JavaDoc sequence = getClassSeqName((String JavaDoc)entry.getKey());
195             ensureSequenceExists(sequence);
196             if (getCurrVal(sequence)<((Long JavaDoc)entry.getValue()).longValue())
197                 execute("select setval('\""+sequence+"\"',"+entry.getValue()+",true)");
198         }
199    }
200
201 }
202
Popular Tags