001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/mailarchive/tags/sakai_2-4-1/mailarchive-impl/impl/src/java/org/sakaiproject/mailarchive/impl/DbMailArchiveService.java $
003: * $Id: DbMailArchiveService.java 8184 2006-04-23 23:45:05Z ggolden@umich.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.mailarchive.impl;
021:
022: import java.sql.Connection;
023: import java.sql.ResultSet;
024: import java.util.List;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.sakaiproject.db.api.SqlReader;
029: import org.sakaiproject.db.api.SqlService;
030: import org.sakaiproject.message.api.Message;
031: import org.sakaiproject.message.api.MessageChannel;
032: import org.sakaiproject.message.api.MessageChannelEdit;
033: import org.sakaiproject.message.api.MessageEdit;
034: import org.sakaiproject.time.api.Time;
035: import org.sakaiproject.util.BaseDbDoubleStorage;
036: import org.sakaiproject.util.StorageUser;
037: import org.sakaiproject.util.Xml;
038: import org.w3c.dom.Document;
039: import org.w3c.dom.Element;
040:
041: /**
042: * <p>
043: * DbMailArchiveService fills out the BaseMailArchiveService with a database implementation.
044: * </p>
045: * <p>
046: * The sql scripts in src/sql/chef_mailarchive.sql must be run on the database.
047: * </p>
048: */
049: public class DbMailArchiveService extends BaseMailArchiveService {
050: /** Our logger. */
051: private static Log M_log = LogFactory
052: .getLog(DbMailArchiveService.class);
053:
054: /** The name of the db table holding mail archive channels. */
055: protected String m_cTableName = "MAILARCHIVE_CHANNEL";
056:
057: /** The name of the db table holding mail archive messages. */
058: protected String m_rTableName = "MAILARCHIVE_MESSAGE";
059:
060: /** If true, we do our locks in the remote database, otherwise we do them here. */
061: protected boolean m_locksInDb = true;
062:
063: protected static final String[] FIELDS = { "MESSAGE_DATE", "OWNER",
064: "DRAFT", "PUBVIEW" };
065:
066: /**********************************************************************************************************************************************************************************************************************************************************
067: * Constructors, Dependencies and their setter methods
068: *********************************************************************************************************************************************************************************************************************************************************/
069:
070: /** Dependency: SqlService */
071: protected SqlService m_sqlService = null;
072:
073: /**
074: * Dependency: SqlService.
075: *
076: * @param service
077: * The SqlService.
078: */
079: public void setSqlService(SqlService service) {
080: m_sqlService = service;
081: }
082:
083: /**
084: * Configuration: set the table name for the container.
085: *
086: * @param path
087: * The table name for the container.
088: */
089: public void setContainerTableName(String name) {
090: m_cTableName = name;
091: }
092:
093: /**
094: * Configuration: set the table name for the resource.
095: *
096: * @param path
097: * The table name for the resource.
098: */
099: public void setResourceTableName(String name) {
100: m_rTableName = name;
101: }
102:
103: /**
104: * Configuration: set the locks-in-db
105: *
106: * @param path
107: * The storage path.
108: */
109: public void setLocksInDb(String value) {
110: m_locksInDb = new Boolean(value).booleanValue();
111: }
112:
113: /** Set if we are to run the to-draft/owner conversion. */
114: protected boolean m_convertToDraft = false;
115:
116: /**
117: * Configuration: run the to-draft/owner conversion
118: *
119: * @param value
120: * The conversion desired value.
121: */
122: public void setConvertDraft(String value) {
123: m_convertToDraft = new Boolean(value).booleanValue();
124: }
125:
126: /** Configuration: to run the ddl on init or not. */
127: protected boolean m_autoDdl = false;
128:
129: /**
130: * Configuration: to run the ddl on init or not.
131: *
132: * @param value
133: * the auto ddl value.
134: */
135: public void setAutoDdl(String value) {
136: m_autoDdl = new Boolean(value).booleanValue();
137: }
138:
139: /**********************************************************************************************************************************************************************************************************************************************************
140: * Init and Destroy
141: *********************************************************************************************************************************************************************************************************************************************************/
142:
143: /**
144: * Final initialization, once all dependencies are set.
145: */
146: public void init() {
147: try {
148: // if we are auto-creating our schema, check and create
149: if (m_autoDdl) {
150: m_sqlService.ddl(this .getClass().getClassLoader(),
151: "sakai_mailarchive");
152: }
153:
154: super .init();
155:
156: M_log.info("init(): tables: " + m_cTableName + " "
157: + m_rTableName + " locks-in-db: " + m_locksInDb);
158:
159: // convert?
160: if (m_convertToDraft) {
161: m_convertToDraft = false;
162: convertToDraft();
163: }
164: } catch (Throwable t) {
165: M_log.warn("init(): ", t);
166: }
167: }
168:
169: /**********************************************************************************************************************************************************************************************************************************************************
170: * BaseMessageService extensions
171: *********************************************************************************************************************************************************************************************************************************************************/
172:
173: /**
174: * Construct a Storage object.
175: *
176: * @return The new storage object.
177: */
178: protected Storage newStorage() {
179: return new DbStorage(this );
180:
181: } // newStorage
182:
183: /**********************************************************************************************************************************************************************************************************************************************************
184: * Storage implementation
185: *********************************************************************************************************************************************************************************************************************************************************/
186:
187: protected class DbStorage extends BaseDbDoubleStorage implements
188: Storage {
189: /**
190: * Construct.
191: *
192: * @param user
193: * The StorageUser class to call back for creation of Resource and Edit objects.
194: */
195: public DbStorage(StorageUser user) {
196: super (m_cTableName, "CHANNEL_ID", m_rTableName,
197: "MESSAGE_ID", "CHANNEL_ID", "MESSAGE_DATE",
198: "OWNER", "DRAFT", "PUBVIEW", FIELDS, m_locksInDb,
199: "channel", "message", user, m_sqlService);
200:
201: } // DbStorage
202:
203: /** Channels * */
204:
205: public boolean checkChannel(String ref) {
206: return super .getContainer(ref) != null;
207: }
208:
209: public MessageChannel getChannel(String ref) {
210: return (MessageChannel) super .getContainer(ref);
211: }
212:
213: public List getChannels() {
214: return super .getAllContainers();
215: }
216:
217: public MessageChannelEdit putChannel(String ref) {
218: return (MessageChannelEdit) super .putContainer(ref);
219: }
220:
221: public MessageChannelEdit editChannel(String ref) {
222: return (MessageChannelEdit) super .editContainer(ref);
223: }
224:
225: public void commitChannel(MessageChannelEdit edit) {
226: super .commitContainer(edit);
227: }
228:
229: public void cancelChannel(MessageChannelEdit edit) {
230: super .cancelContainer(edit);
231: }
232:
233: public void removeChannel(MessageChannelEdit edit) {
234: super .removeContainer(edit);
235: }
236:
237: public List getChannelIdsMatching(String root) {
238: return super .getContainerIdsMatching(root);
239: }
240:
241: /** messages * */
242:
243: public boolean checkMessage(MessageChannel channel, String id) {
244: return super .checkResource(channel, id);
245: }
246:
247: public Message getMessage(MessageChannel channel, String id) {
248: return (Message) super .getResource(channel, id);
249: }
250:
251: public List getMessages(MessageChannel channel) {
252: return super .getAllResources(channel);
253: }
254:
255: public MessageEdit putMessage(MessageChannel channel, String id) {
256: return (MessageEdit) super .putResource(channel, id, null);
257: }
258:
259: public MessageEdit editMessage(MessageChannel channel, String id) {
260: return (MessageEdit) super .editResource(channel, id);
261: }
262:
263: public void commitMessage(MessageChannel channel,
264: MessageEdit edit) {
265: super .commitResource(channel, edit);
266: }
267:
268: public void cancelMessage(MessageChannel channel,
269: MessageEdit edit) {
270: super .cancelResource(channel, edit);
271: }
272:
273: public void removeMessage(MessageChannel channel,
274: MessageEdit edit) {
275: super .removeResource(channel, edit);
276: }
277:
278: public List getMessages(MessageChannel channel, Time afterDate,
279: int limitedToLatest, String draftsForId,
280: boolean pubViewOnly) {
281: return super .getResources(channel, afterDate,
282: limitedToLatest, draftsForId, pubViewOnly);
283: }
284:
285: } // DbStorage
286:
287: /**
288: * fill in the draft and owner db fields
289: */
290: protected void convertToDraft() {
291: M_log.info("convertToDraft");
292:
293: try {
294: // get a connection
295: final Connection connection = m_sqlService
296: .borrowConnection();
297: boolean wasCommit = connection.getAutoCommit();
298: connection.setAutoCommit(false);
299:
300: // read all message records that need conversion
301: String sql = "select CHANNEL_ID, MESSAGE_ID, XML from "
302: + m_rTableName /* + " where OWNER is null" */;
303: m_sqlService.dbRead(connection, sql, null, new SqlReader() {
304: private int count = 0;
305:
306: public Object readSqlResultRecord(ResultSet result) {
307: try {
308: // create the Resource from the db xml
309: String channelId = result.getString(1);
310: String messageId = result.getString(2);
311: String xml = result.getString(3);
312:
313: // read the xml
314: Document doc = Xml.readDocumentFromString(xml);
315:
316: // verify the root element
317: Element root = doc.getDocumentElement();
318: if (!root.getTagName().equals("message")) {
319: M_log
320: .warn("convertToDraft(): XML root element not message: "
321: + root.getTagName());
322: return null;
323: }
324: Message m = new BaseMessageEdit(null, root);
325:
326: // pick up the fields
327: String owner = m.getHeader().getFrom().getId();
328: boolean draft = m.getHeader().getDraft();
329:
330: // update
331: String update = "update "
332: + m_rTableName
333: + " set OWNER = ?, DRAFT = ? where CHANNEL_ID = ? and MESSAGE_ID = ?";
334: Object fields[] = new Object[4];
335: fields[0] = owner;
336: fields[1] = (draft ? "1" : "0");
337: fields[2] = channelId;
338: fields[3] = messageId;
339: boolean ok = m_sqlService.dbWrite(connection,
340: update, fields);
341:
342: if (!ok)
343: M_log
344: .info("convertToDraft: channel: "
345: + channelId + " message: "
346: + messageId + " owner: "
347: + owner + " draft: "
348: + draft + " ok: " + ok);
349:
350: count++;
351: if (count % 100 == 0) {
352: M_log.info("convertToDraft: " + count);
353: }
354: return null;
355: } catch (Throwable ignore) {
356: return null;
357: }
358: }
359: });
360:
361: connection.commit();
362: connection.setAutoCommit(wasCommit);
363: m_sqlService.returnConnection(connection);
364: } catch (Throwable t) {
365: M_log.warn("convertToDraft: failed: " + t);
366: }
367:
368: M_log.info("convertToDraft: done");
369: }
370:
371: } // DbCachedMailArchiveService
|