001: /*
002: Very Quick Wiki - WikiWikiWeb clone
003: Copyright (C) 2001-2002 Gareth Cronin
004:
005: This program is free software; you can redistribute it and/or modify
006: it under the terms of the latest version of the GNU Lesser General
007: Public License as published by the Free Software Foundation;
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 (gpl.txt); if not, write to the Free Software
016: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: */
018: package vqwiki.db;
019:
020: import vqwiki.Environment;
021: import vqwiki.TopicVersion;
022: import vqwiki.VersionManager;
023: import vqwiki.utils.DiffUtil;
024:
025: import java.sql.Connection;
026: import java.sql.PreparedStatement;
027: import java.sql.ResultSet;
028: import java.sql.Timestamp;
029: import java.util.ArrayList;
030: import java.util.Date;
031: import java.util.List;
032:
033: import org.apache.log4j.Logger;
034:
035: public class DatabaseVersionManager implements VersionManager {
036:
037: protected final static String STATEMENT_VERSION_FIND = "SELECT * FROM TopicVersion WHERE name = ? AND virtualwiki = ? ORDER BY versionat DESC";
038: protected final static String STATEMENT_ADD_VERSION = "INSERT INTO TopicVersion (virtualwiki, name, contents, versionat) VALUES( ?, ?, ?, ?)";
039: protected final static String STATEMENT_ADD_VERSION_ORACLE1 = "INSERT INTO TopicVersion (virtualwiki, name, contents, versionat) VALUES( ?, ?, EMPTY_CLOB(), ?)";
040: protected final static String STATEMENT_ADD_VERSION_ORACLE2 = "SELECT contents FROM TopicVersion WHERE name = ? AND virtualwiki = ? ORDER BY versionat DESC FOR UPDATE";
041: protected final static String STATEMENT_VERSION_FIND_ONE = "SELECT * FROM TopicVersion WHERE name = ? AND virtualwiki = ? AND versionAt = ?";
042: protected final static String STATEMENT_GET_ALL = "SELECT versionat FROM TopicVersion WHERE name = ? AND virtualwiki = ? ORDER BY versionat DESC";
043: protected final static String STATEMENT_COUNT_VERSIONS = "SELECT COUNT(*) FROM TopicVersion WHERE name = ? AND virtualwiki = ?";
044:
045: protected static DatabaseVersionManager instance;
046: private static final Logger logger = Logger
047: .getLogger(DatabaseVersionManager.class);
048:
049: /**
050: *
051: */
052: private DatabaseVersionManager() throws Exception {
053: }
054:
055: /**
056: *
057: */
058: public static DatabaseVersionManager getInstance() throws Exception {
059: if (instance == null)
060: instance = new DatabaseVersionManager();
061: return instance;
062: }
063:
064: /**
065: *
066: */
067: public Object lookupLastRevision(String virtualWiki,
068: String topicName) throws Exception {
069: // improvement would be: find max "versionat" for revisions
070: // return the date as a string
071: return lookupRevision(virtualWiki, topicName, 0);
072: }
073:
074: /**
075: *
076: */
077: public Object lookupRevision(String virtualWiki, String topicName,
078: int version) throws Exception {
079: if (version < 0)
080: throw new Exception("version # must be >= 0");
081: Connection conn = null;
082: Timestamp stamp = null;
083: try {
084: conn = DatabaseConnection.getConnection();
085: PreparedStatement versionFindStatement = conn
086: .prepareStatement(STATEMENT_VERSION_FIND);
087: versionFindStatement.setString(1, topicName);
088: versionFindStatement.setString(2, virtualWiki);
089: ResultSet rs = versionFindStatement.executeQuery();
090: for (int i = 0; i <= version; i++) {
091: if (!rs.next()) {
092: rs.close();
093: versionFindStatement.close();
094: return null;
095: }
096: }
097: stamp = rs.getTimestamp("versionat");
098: logger.debug("Revision #" + version + " @" + stamp);
099: rs.close();
100: versionFindStatement.close();
101: } finally {
102: DatabaseConnection.closeConnection(conn);
103: }
104: return stamp;
105: }
106:
107: /**
108: *
109: */
110: public String revisionContents(String virtualWiki,
111: String topicName, Timestamp date) throws Exception {
112: Connection conn = null;
113: String contents;
114: try {
115: conn = DatabaseConnection.getConnection();
116: PreparedStatement versionFindStatementOne = conn
117: .prepareStatement(STATEMENT_VERSION_FIND_ONE);
118: versionFindStatementOne.setString(1, topicName);
119: versionFindStatementOne.setString(2, virtualWiki);
120: versionFindStatementOne.setTimestamp(3, date);
121: ResultSet rs = versionFindStatementOne.executeQuery();
122: if (!rs.next()) {
123: rs.close();
124: versionFindStatementOne.close();
125: return null;
126: }
127: if (Environment.getInstance().isOracle()) {
128: contents = OracleClobHelper.getClobValue(rs
129: .getClob("contents"));
130: } else {
131: contents = rs.getString("contents");
132: }
133: logger.debug("Contents @" + date + ": " + contents);
134: rs.close();
135: versionFindStatementOne.close();
136: } finally {
137: DatabaseConnection.closeConnection(conn);
138: }
139: return contents;
140: }
141:
142: /**
143: *
144: */
145: public String diff(String virtualWiki, String topicName,
146: int revision1, int revision2, boolean useHtml)
147: throws Exception {
148: logger.debug("Diff for version " + revision1
149: + " against version " + revision2 + ", " + virtualWiki
150: + "/" + topicName);
151: String contents1 = revisionContents(virtualWiki, topicName,
152: (Timestamp) lookupRevision(virtualWiki, topicName,
153: revision1));
154: String contents2 = revisionContents(virtualWiki, topicName,
155: (Timestamp) lookupRevision(virtualWiki, topicName,
156: revision2));
157: if (contents1 == null && contents2 == null) {
158: logger.error("No versions found for " + revision1
159: + " against " + revision2);
160: return "";
161: }
162: return DiffUtil.diff(contents1, contents2, useHtml);
163: }
164:
165: /**
166: *
167: */
168: public Date lastRevisionDate(String virtualWiki, String topicName)
169: throws Exception {
170: Timestamp stamp = (Timestamp) lookupLastRevision(virtualWiki,
171: topicName);
172: if (stamp == null)
173: return null;
174: return new Date(stamp.getTime());
175: }
176:
177: /**
178: *
179: */
180: public List getAllVersions(String virtualWiki, String topicName)
181: throws Exception {
182: List all = new ArrayList();
183: Connection conn = null;
184: try {
185: conn = DatabaseConnection.getConnection();
186: PreparedStatement getAllStatement = conn
187: .prepareStatement(STATEMENT_GET_ALL);
188: getAllStatement.setString(1, topicName);
189: getAllStatement.setString(2, virtualWiki);
190: ResultSet rs = getAllStatement.executeQuery();
191: for (int i = 0; rs.next(); i++) {
192: TopicVersion version = new TopicVersion(virtualWiki,
193: topicName, new DBDate(rs
194: .getTimestamp("versionat")), i);
195: all.add(version);
196: }
197: rs.close();
198: getAllStatement.close();
199: } finally {
200: DatabaseConnection.closeConnection(conn);
201: }
202: return all;
203: }
204:
205: /**
206: *
207: */
208: public TopicVersion getTopicVersion(String virtualWiki,
209: String topicName, int versionNumber) throws Exception {
210: List allVersions = getAllVersions(virtualWiki, topicName);
211: return (TopicVersion) allVersions.get(versionNumber);
212: }
213:
214: /**
215: *
216: */
217: public String getVersionContents(String virtualWiki,
218: String topicName, int versionNumber) throws Exception {
219: Timestamp stamp = (Timestamp) lookupRevision(virtualWiki,
220: topicName, versionNumber);
221: return revisionContents(virtualWiki, topicName, stamp);
222: }
223:
224: /**
225: *
226: */
227: public int getNumberOfVersions(String virtualWiki, String topicName)
228: throws Exception {
229: Connection conn = null;
230: try {
231: conn = DatabaseConnection.getConnection();
232: PreparedStatement getAllStatement = conn
233: .prepareStatement(STATEMENT_COUNT_VERSIONS);
234: getAllStatement.setString(1, topicName);
235: getAllStatement.setString(2, virtualWiki);
236: ResultSet rs = getAllStatement.executeQuery();
237: if (rs.next()) {
238: int count = rs.getInt(1);
239: rs.close();
240: getAllStatement.close();
241: return count;
242: }
243: rs.close();
244: getAllStatement.close();
245: } finally {
246: DatabaseConnection.closeConnection(conn);
247: }
248: return -1;
249: }
250:
251: /**
252: *
253: */
254: public void addVersion(String virtualWiki, String topicName,
255: String contents, Date at) throws Exception {
256: Connection conn = null;
257: try {
258: conn = DatabaseConnection.getConnection();
259: PreparedStatement addStatement;
260: if (Environment.getInstance().isOracle()) {
261: boolean savedAutoCommit = conn.getAutoCommit();
262: conn.setAutoCommit(false);
263: addStatement = conn
264: .prepareStatement(STATEMENT_ADD_VERSION_ORACLE1);
265: addStatement.setString(1, virtualWiki);
266: addStatement.setString(2, topicName);
267: addStatement.setTimestamp(3, new DBDate(at)
268: .asTimestamp());
269: addStatement.execute();
270: addStatement.close();
271: conn.commit();
272: addStatement = conn.prepareStatement(
273: STATEMENT_ADD_VERSION_ORACLE2,
274: ResultSet.TYPE_SCROLL_INSENSITIVE,
275: ResultSet.CONCUR_UPDATABLE);
276: addStatement.setString(1, topicName);
277: addStatement.setString(2, virtualWiki);
278: ResultSet rs = addStatement.executeQuery();
279: rs.next();
280: OracleClobHelper.setClobValue(rs.getClob(1), contents);
281: rs.close();
282: addStatement.close();
283: conn.commit();
284: conn.setAutoCommit(savedAutoCommit);
285: } else {
286: addStatement = conn
287: .prepareStatement(STATEMENT_ADD_VERSION);
288: addStatement.setString(1, virtualWiki);
289: addStatement.setString(2, topicName);
290: addStatement.setString(3, contents);
291: addStatement.setTimestamp(4, new DBDate(at)
292: .asTimestamp());
293: addStatement.execute();
294: addStatement.close();
295: }
296: } finally {
297: DatabaseConnection.closeConnection(conn);
298: }
299: }
300: }
|