001: /**
002: * Copyright (C) 2001 Yasna.com. All rights reserved.
003: *
004: * ===================================================================
005: * The Apache Software License, Version 1.1
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution,
020: * if any, must include the following acknowledgment:
021: * "This product includes software developed by
022: * Yasna.com (http://www.yasna.com)."
023: * Alternately, this acknowledgment may appear in the software itself,
024: * if and wherever such third-party acknowledgments normally appear.
025: *
026: * 4. The names "Yazd" and "Yasna.com" must not be used to
027: * endorse or promote products derived from this software without
028: * prior written permission. For written permission, please
029: * contact yazd@yasna.com.
030: *
031: * 5. Products derived from this software may not be called "Yazd",
032: * nor may "Yazd" appear in their name, without prior written
033: * permission of Yasna.com.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL YASNA.COM OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of Yasna.com. For more information
051: * on Yasna.com, please see <http://www.yasna.com>.
052: */package com.Yasna.forum.database;
053:
054: import java.util.Iterator;
055: import java.util.Enumeration;
056: import java.util.Properties;
057: import java.util.ArrayList;
058: import java.util.Date;
059: import java.sql.*;
060: import java.io.*;
061:
062: import com.Yasna.forum.*;
063: import com.Yasna.forum.filter.*;
064: import com.Yasna.util.Cache;
065: import com.Yasna.util.Cacheable;
066: import com.Yasna.util.CacheSizes;
067:
068: /**
069: * Database implementation of the Category interface. It loads and stores category
070: * information from the database.
071: *
072: * @see Category
073: */
074: public class DbCategory implements Category, Cacheable {
075:
076: /** DATABASE QUERIES **/
077: private static final String LOAD_CATEGORY_BY_ID = "SELECT categoryID, name, description, creationDate, modifiedDate,catorder FROM yazdCategory WHERE CategoryID=?";
078: private static final String LOAD_CATEGORY_BY_NAME = "SELECT categoryID, name, description, creationDate, modifiedDate,catorder FROM yazdCategory WHERE name=?";
079: private static final String UPDATE_CATEGORY_MODIFIED_DATE = "UPDATE yazdCategory SET modifiedDate=? WHERE categoryID=?";
080: private static final String ADD_CATEGORY = "INSERT INTO yazdCategory(categoryID, name, description, creationDate, "
081: + "modifiedDate,catorder) VALUES (?,?,?,?,?,0)";
082: private static final String SAVE_CATEGORY = "UPDATE yazdCategory SET name=?, description=?, creationDate=?, "
083: + "modifiedDate=?,catorder=? WHERE categoryID=?";
084: private static final String DELETE_FORUM_GROUP = "DELETE FROM yazdForumGroup WHERE forumGroupID=?";
085:
086: private int id = -1;
087: private String name;
088: private String description;
089: private java.util.Date creationDate;
090: private java.util.Date modifiedDate;
091:
092: private DbForumFactory factory;
093: private int catorder = 0;
094:
095: /**
096: * Creates a new category with the specified name and description.
097: *
098: * @param name the name of the category.
099: * @param description the description of the category.
100: * @param factory the DbForumFactory that will hold the category.
101: */
102: protected DbCategory(String name, String description,
103: DbForumFactory factory) {
104: this .id = DbSequenceManager.nextID("Category");
105: this .name = name;
106: this .description = description;
107: long now = System.currentTimeMillis();
108: creationDate = new java.util.Date(now);
109: modifiedDate = new java.util.Date(now);
110: this .factory = factory;
111: insertIntoDb();
112: }
113:
114: /**
115: * Loads a category with the specified id.
116: */
117: protected DbCategory(int id, DbForumFactory factory)
118: throws CategoryNotFoundException {
119: this .id = id;
120: this .factory = factory;
121: loadFromDb();
122: }
123:
124: /**
125: * Loads a category with the specified name.
126: */
127: protected DbCategory(String name, DbForumFactory factory)
128: throws CategoryNotFoundException {
129: this .name = name;
130: this .factory = factory;
131: loadFromDb();
132: }
133:
134: //FROM THE CATEGORY INTERFACE//
135:
136: public int getID() {
137: return id;
138: }
139:
140: public String getName() {
141: return name;
142: }
143:
144: public int getOrder() {
145: return this .catorder;
146: }
147:
148: public void setOrder(int param) throws UnauthorizedException {
149: this .catorder = param;
150: saveToDb();
151: }
152:
153: public void setName(String name) throws UnauthorizedException {
154: this .name = name;
155: saveToDb();
156: }
157:
158: public String getDescription() {
159: return description;
160: }
161:
162: public void setDescription(String description)
163: throws UnauthorizedException {
164: this .description = description;
165: saveToDb();
166: }
167:
168: public java.util.Date getCreationDate() {
169: return creationDate;
170: }
171:
172: public void setCreationDate(java.util.Date creationDate)
173: throws UnauthorizedException {
174: this .creationDate = creationDate;
175: saveToDb();
176: }
177:
178: public java.util.Date getModifiedDate() {
179: return modifiedDate;
180: }
181:
182: public void setModifiedDate(java.util.Date modifiedDate)
183: throws UnauthorizedException {
184: this .modifiedDate = modifiedDate;
185: saveToDb();
186: }
187:
188: public Iterator forumGroups() {
189: return new DbForumGroupIterator(this , factory);
190: }
191:
192: public ForumGroup getForumGroup(int forumGroupID)
193: throws ForumGroupNotFoundException {
194: return factory.getForumGroup(forumGroupID, this );
195: }
196:
197: public ForumGroup createForumGroup(String name, String description)
198: throws UnauthorizedException {
199: return new DbForumGroup(name, description, this , factory);
200: }
201:
202: public void deleteForumGroup(ForumGroup forumGroup)
203: throws UnauthorizedException {
204: Iterator forumIterator = forumGroup.forums();
205: while (forumIterator.hasNext()) {
206: Forum forumTmp = (Forum) forumIterator.next();
207: factory.deleteForum(forumTmp);
208: }
209:
210: Connection con = null;
211: PreparedStatement pstmt = null;
212: try {
213: con = DbConnectionManager.getConnection();
214: pstmt = con.prepareStatement(DELETE_FORUM_GROUP);
215: pstmt.setInt(1, forumGroup.getID());
216: pstmt.execute();
217: pstmt.close();
218: } catch (Exception sqle) {
219: System.err
220: .println("Error in DbForumFactory:deleteForumGroup()-"
221: + sqle);
222: } finally {
223: try {
224: pstmt.close();
225: } catch (Exception e) {
226: e.printStackTrace();
227: }
228: try {
229: con.close();
230: } catch (Exception e) {
231: e.printStackTrace();
232: }
233: }
234:
235: }
236:
237: //FROM THE CACHEABLE INTERFACE//
238:
239: public int getSize() {
240: //Approximate the size of the object in bytes by calculating the size
241: //of each field.
242: int size = 0;
243: size += CacheSizes.sizeOfObject(); //overhead of object
244: size += CacheSizes.sizeOfObject(); //ref to category
245: size += CacheSizes.sizeOfInt(); //id
246: size += CacheSizes.sizeOfString(name); //name
247: size += CacheSizes.sizeOfString(description); //description
248: size += CacheSizes.sizeOfDate(); //creation date
249: size += CacheSizes.sizeOfDate(); //modified date
250: size += CacheSizes.sizeOfObject(); //save lock
251: size += CacheSizes.sizeOfInt(); //catorder
252:
253: return size;
254: }
255:
256: /**
257: * Updates the modified date but doesn't require a security check since
258: * it is a protected method.
259: */
260: protected void updateModifiedDate(java.util.Date modifiedDate) {
261: this .modifiedDate = modifiedDate;
262: Connection con = null;
263: PreparedStatement pstmt = null;
264: try {
265: con = DbConnectionManager.getConnection();
266: pstmt = con.prepareStatement(UPDATE_CATEGORY_MODIFIED_DATE);
267: pstmt.setString(1, "" + modifiedDate.getTime());
268: pstmt.setInt(2, id);
269: pstmt.executeUpdate();
270: } catch (SQLException sqle) {
271: System.err
272: .println("Error in DbCategory:updateModifiedDate()-"
273: + sqle);
274: sqle.printStackTrace();
275: } finally {
276: try {
277: pstmt.close();
278: } catch (Exception e) {
279: e.printStackTrace();
280: }
281: try {
282: con.close();
283: } catch (Exception e) {
284: e.printStackTrace();
285: }
286: }
287: }
288:
289: /**
290: * Loads category data from the database.
291: */
292: private void loadFromDb() throws CategoryNotFoundException {
293: Connection con = null;
294: PreparedStatement pstmt = null;
295: try {
296: con = DbConnectionManager.getConnection();
297: //See if we should load by categoryID or by name
298: if (id == -1) {
299: pstmt = con.prepareStatement(LOAD_CATEGORY_BY_NAME);
300: pstmt.setString(1, name);
301: } else {
302: pstmt = con.prepareStatement(LOAD_CATEGORY_BY_ID);
303: pstmt.setInt(1, id);
304: }
305: ResultSet rs = pstmt.executeQuery();
306: if (!rs.next()) {
307: throw new CategoryNotFoundException("Category "
308: + getID()
309: + " could not be loaded from the database.");
310: }
311: id = rs.getInt("categoryID");
312: name = rs.getString("name");
313: description = rs.getString("description");
314: this .creationDate = new java.util.Date(Long.parseLong(rs
315: .getString("creationDate").trim()));
316: this .modifiedDate = new java.util.Date(Long.parseLong(rs
317: .getString("modifiedDate").trim()));
318: catorder = rs.getInt("catorder");
319: } catch (SQLException sqle) {
320: sqle.printStackTrace();
321: throw new CategoryNotFoundException("Category " + getID()
322: + " could not be loaded from the database.");
323: } catch (NumberFormatException nfe) {
324: System.err
325: .println("WARNING: In DbCAtegory.loadFromDb() -- there "
326: + "was an error parsing the dates returned from the database. Ensure "
327: + "that they're being stored correctly.");
328: } finally {
329: try {
330: pstmt.close();
331: } catch (Exception e) {
332: e.printStackTrace();
333: }
334: try {
335: con.close();
336: } catch (Exception e) {
337: e.printStackTrace();
338: }
339: }
340: }
341:
342: /**
343: * Inserts a new record into the database.
344: */
345: private void insertIntoDb() {
346: Connection con = null;
347: PreparedStatement pstmt = null;
348: try {
349: con = DbConnectionManager.getConnection();
350: pstmt = con.prepareStatement(ADD_CATEGORY);
351: pstmt.setInt(1, id);
352: pstmt.setString(2, name);
353: pstmt.setString(3, description);
354: pstmt.setString(4, Long.toString(creationDate.getTime()));
355: pstmt.setString(5, Long.toString(modifiedDate.getTime()));
356: pstmt.executeUpdate();
357: } catch (SQLException sqle) {
358: System.err.println("Error in DbCategory:insertIntoDb()-"
359: + sqle);
360: sqle.printStackTrace();
361: } finally {
362: try {
363: pstmt.close();
364: } catch (Exception e) {
365: e.printStackTrace();
366: }
367: try {
368: con.close();
369: } catch (Exception e) {
370: e.printStackTrace();
371: }
372: }
373: }
374:
375: /**
376: * Saves category data to the database.
377: */
378: private synchronized void saveToDb() {
379: Connection con = null;
380: PreparedStatement pstmt = null;
381: try {
382: con = DbConnectionManager.getConnection();
383: pstmt = con.prepareStatement(SAVE_CATEGORY);
384: pstmt.setString(1, name);
385: pstmt.setString(2, description);
386: pstmt.setString(3, Long.toString(creationDate.getTime()));
387: pstmt.setString(4, Long.toString(modifiedDate.getTime()));
388: pstmt.setInt(5, catorder);
389: pstmt.setInt(6, id);
390: pstmt.executeUpdate();
391: } catch (SQLException sqle) {
392: System.err.println("Error in DbForum:saveToDb()-" + sqle);
393: sqle.printStackTrace();
394: } finally {
395: try {
396: pstmt.close();
397: } catch (Exception e) {
398: e.printStackTrace();
399: }
400: try {
401: con.close();
402: } catch (Exception e) {
403: e.printStackTrace();
404: }
405: }
406: }
407: }
|