001: package org.claros.intouch.webmail.controllers;
002:
003: import java.io.ByteArrayInputStream;
004: import java.sql.SQLException;
005: import java.util.ArrayList;
006: import java.util.HashMap;
007: import java.util.List;
008: import java.util.Properties;
009:
010: import javax.mail.Message;
011: import javax.mail.MessagingException;
012: import javax.mail.Session;
013: import javax.mail.internet.MimeMessage;
014:
015: import org.apache.commons.dbutils.QueryRunner;
016: import org.apache.commons.dbutils.handlers.MapHandler;
017: import org.apache.commons.logging.Log;
018: import org.apache.commons.logging.LogFactory;
019: import org.claros.commons.auth.models.AuthProfile;
020: import org.claros.commons.db.DbConfigList;
021: import org.claros.commons.exception.NoPermissionException;
022: import org.claros.commons.exception.SystemException;
023: import org.claros.commons.mail.models.ConnectionMetaHandler;
024: import org.claros.commons.mail.models.ConnectionProfile;
025: import org.claros.commons.mail.models.EmailHeader;
026: import org.claros.commons.mail.protocols.Protocol;
027: import org.claros.commons.mail.protocols.ProtocolFactory;
028: import org.claros.commons.utility.Formatter;
029: import org.claros.intouch.common.utility.Constants;
030: import org.claros.intouch.common.utility.Utility;
031: import org.claros.intouch.webmail.factory.FolderControllerFactory;
032: import org.claros.intouch.webmail.models.MsgDbObject;
033: import org.claros.intouch.webmail.models.FolderDbObject;
034: import org.claros.intouch.webmail.models.FolderDbObjectWrapper;
035:
036: import com.jenkov.mrpersister.impl.mapping.AutoGeneratedColumnsMapper;
037: import com.jenkov.mrpersister.itf.IGenericDao;
038: import com.jenkov.mrpersister.itf.mapping.IObjectMappingKey;
039: import com.jenkov.mrpersister.util.JdbcUtil;
040:
041: /**
042: * @author Umut Gokbayrak
043: */
044: public class DbFolderControllerImpl implements FolderController {
045: private static Log log = LogFactory
046: .getLog(DbFolderControllerImpl.class);
047: private AuthProfile auth;
048: private ConnectionProfile profile;
049: private ConnectionMetaHandler handler;
050:
051: /**
052: * @param auth
053: */
054: public DbFolderControllerImpl(AuthProfile auth,
055: ConnectionProfile profile, ConnectionMetaHandler handler) {
056: this .auth = auth;
057: this .profile = profile;
058: this .handler = handler;
059: }
060:
061: /**
062: * used to disable it.
063: *
064: */
065: private DbFolderControllerImpl() {
066: super ();
067: }
068:
069: /**
070: * only meaningful for inbox, sent, junk, trash
071: * @param auth
072: * @return
073: */
074: private FolderDbObject getSpecialFolderByType(Integer folderType)
075: throws Exception {
076: IGenericDao dao = null;
077: FolderDbObject folder = null;
078: try {
079: dao = Utility.getDbConnection();
080: String username = auth.getUsername();
081:
082: String sql = "SELECT * FROM FOLDER_DB_OBJECTS WHERE USERNAME=? AND FOLDER_TYPE = ?";
083: folder = (FolderDbObject) dao.read(FolderDbObject.class,
084: sql, new Object[] { username, folderType });
085: } finally {
086: JdbcUtil.close(dao);
087: dao = null;
088: }
089: return folder;
090: }
091:
092: /**
093: * @param auth
094: * @return
095: */
096: public FolderDbObject getJunkFolder() throws Exception {
097: return getSpecialFolderByType(Constants.FOLDER_TYPE_JUNK);
098: }
099:
100: /**
101: * @param auth
102: * @return
103: */
104: public FolderDbObject getInboxFolder() throws Exception {
105: return getSpecialFolderByType(Constants.FOLDER_TYPE_INBOX);
106: }
107:
108: /**
109: * @param auth
110: * @return
111: */
112: public FolderDbObject getSentItems() throws Exception {
113: return getSpecialFolderByType(Constants.FOLDER_TYPE_SENT);
114: }
115:
116: /**
117: * @param auth
118: * @return
119: */
120: public FolderDbObject getTrashFolder() throws Exception {
121: return getSpecialFolderByType(Constants.FOLDER_TYPE_TRASH);
122: }
123:
124: /**
125: * @param auth
126: * @return
127: */
128: public FolderDbObject getDraftsFolder() throws Exception {
129: return getSpecialFolderByType(Constants.FOLDER_TYPE_DRAFTS);
130: }
131:
132: /* (non-Javadoc)
133: * @see org.claros.groupware.webmail.controllers.FolderController#getFolders(org.claros.commons.models.AuthProfile)
134: */
135: public List getFolders() throws Exception {
136: IGenericDao dao = null;
137: ArrayList myList = null;
138: try {
139: dao = Utility.getDbConnection();
140: String username = auth.getUsername();
141:
142: String sql = "SELECT * FROM FOLDER_DB_OBJECTS WHERE USERNAME=?";
143: List folders = dao.readList(FolderDbObject.class, sql,
144: new Object[] { username });
145:
146: myList = new ArrayList();
147: if (folders != null) {
148: FolderDbObject tmp = null;
149: for (int i = 0; i < folders.size(); i++) {
150: tmp = (FolderDbObject) folders.get(i);
151: FolderDbObjectWrapper fd = new FolderDbObjectWrapper(
152: tmp);
153: try {
154: fd.setUnreadItemCount(countUnreadMessages(tmp
155: .getId().toString()));
156: fd.setTotalItemCount(countTotalMessages(tmp
157: .getId().toString()));
158: } catch (Exception f) {
159: log
160: .debug("unable to fetch unread/total count for folder");
161: }
162: myList.add(fd);
163: }
164: }
165: } finally {
166: JdbcUtil.close(dao);
167: dao = null;
168: }
169: return myList;
170: }
171:
172: /* (non-Javadoc)
173: * @see org.claros.groupware.webmail.controllers.FolderController#getFolder(org.claros.commons.models.AuthProfile, java.lang.String)
174: */
175: public FolderDbObject getFolder(String folder) throws Exception {
176: IGenericDao dao = null;
177: FolderDbObject fld = null;
178: try {
179: Long lFolder = new Long(folder);
180:
181: dao = Utility.getDbConnection();
182: String username = auth.getUsername();
183:
184: String sql = "SELECT * FROM FOLDER_DB_OBJECTS WHERE USERNAME=? AND ID = ?";
185: fld = (FolderDbObject) dao.read(FolderDbObject.class, sql,
186: new Object[] { username, lFolder });
187: } finally {
188: JdbcUtil.close(dao);
189: dao = null;
190: }
191: return fld;
192: }
193:
194: /* (non-Javadoc)
195: * @see org.claros.groupware.webmail.controllers.FolderController#getMailsByFolder(org.claros.commons.models.AuthProfile, java.lang.String)
196: */
197: public List getMailsByFolder(String folder) throws Exception {
198: IGenericDao dao = null;
199: List msgs = null;
200: try {
201: Long folderId = new Long(folder);
202: dao = Utility.getDbConnection();
203: String username = auth.getUsername();
204:
205: String sql = "SELECT * FROM MSG_DB_OBJECTS WHERE USERNAME=? AND FOLDER_ID = ?";
206: msgs = dao.readList(MsgDbObject.class, sql, new Object[] {
207: username, folderId });
208: } finally {
209: JdbcUtil.close(dao);
210: dao = null;
211: }
212: return msgs;
213: }
214:
215: /* (non-Javadoc)
216: * @see org.claros.groupware.webmail.controllers.FolderController#createFolder(org.claros.groupware.webmail.models.FolderDbItem)
217: */
218: public void createFolder(FolderDbObject item) throws Exception {
219: IGenericDao dao = null;
220: try {
221: dao = Utility.getDbConnection();
222:
223: IObjectMappingKey myObj = org.claros.intouch.common.utility.Constants.persistMan
224: .getObjectMappingFactory().createInstance(
225: FolderDbObject.class,
226: new AutoGeneratedColumnsMapper(true));
227: dao.insert(myObj, item);
228: } finally {
229: JdbcUtil.close(dao);
230: dao = null;
231: }
232: }
233:
234: /* (non-Javadoc)
235: * @see org.claros.groupware.webmail.controllers.FolderController#countUnreadMessages(org.claros.commons.models.AuthProfile, java.lang.Long)
236: */
237: public Integer countUnreadMessages(String folder) throws Exception {
238: FolderDbObject foldObj = getInboxFolder();
239: if (foldObj.getId().toString().equals(folder)) {
240: // it is the INBOX
241: ProtocolFactory pFact = new ProtocolFactory(profile, auth,
242: handler);
243: Protocol prot = pFact.getPop3();
244: return new Integer(prot.getTotalMessageCount());
245: } else {
246: QueryRunner run = new QueryRunner(DbConfigList
247: .getDataSourceById("file"));
248: HashMap result = null;
249: String username = auth.getUsername();
250: try {
251: Long folderId = new Long(folder);
252: String sql = "SELECT COUNT(*) AS NUMBER FROM MSG_DB_OBJECTS WHERE USERNAME=? AND FOLDER_ID = ? AND UNREAD = ?";
253: result = (HashMap) run.query(sql, new Object[] {
254: username, folderId, new Boolean(true) },
255: new MapHandler());
256: } catch (SQLException e) {
257: return new Integer(0);
258: }
259: if (result != null) {
260: return new Integer(result.get("number").toString());
261: }
262: }
263: return new Integer(0);
264: }
265:
266: /* (non-Javadoc)
267: * @see org.claros.groupware.webmail.controllers.FolderController#countTotalMessages(org.claros.commons.models.AuthProfile, java.lang.String)
268: */
269: public Integer countTotalMessages(String folder) throws Exception {
270: FolderDbObject foldObj = getInboxFolder();
271: if (foldObj.getId().toString().equals(folder)) {
272: // it is the INBOX
273: ProtocolFactory pFact = new ProtocolFactory(profile, auth,
274: handler);
275: Protocol prot = pFact.getPop3();
276: return new Integer(prot.getTotalMessageCount());
277: } else {
278: // it is a database folder
279: QueryRunner run = new QueryRunner(DbConfigList
280: .getDataSourceById("file"));
281: HashMap result = null;
282: String username = auth.getUsername();
283: try {
284: Long folderId = new Long(folder);
285: String sql = "SELECT COUNT(*) AS NUMBER FROM MSG_DB_OBJECTS WHERE USERNAME=? AND FOLDER_ID = ? ";
286: result = (HashMap) run.query(sql, new Object[] {
287: username, folderId }, new MapHandler());
288: } catch (SQLException e) {
289: return new Integer(0);
290: }
291: if (result != null) {
292: return new Integer(result.get("number").toString());
293: }
294: }
295: return new Integer(0);
296: }
297:
298: /* (non-Javadoc)
299: * @see org.claros.groupware.webmail.controllers.FolderController#emptyFolder(org.claros.commons.models.AuthProfile, java.lang.String)
300: */
301: public void emptyFolder(String folder) throws Exception {
302: FolderDbObject foldObj = getInboxFolder();
303: if (foldObj.getId().toString().equals(folder)) {
304: // it is the INBOX
305: ProtocolFactory pFact = new ProtocolFactory(profile, auth,
306: handler);
307: Protocol prot = pFact.getPop3();
308: prot.emptyFolder();
309: } else {
310: // it is a database folder
311: QueryRunner run = new QueryRunner(DbConfigList
312: .getDataSourceById("file"));
313: String username = auth.getUsername();
314: try {
315: Long folderId = new Long(folder);
316: String sql = "DELETE FROM MSG_DB_OBJECTS WHERE USERNAME=? AND FOLDER_ID=?";
317: run.update(sql, new Object[] { username, folderId });
318: } catch (SQLException e) {
319: throw e;
320: }
321: }
322: }
323:
324: /* (non-Javadoc)
325: * @see org.claros.groupware.webmail.controllers.FolderController#deleteFolder(org.claros.commons.models.AuthProfile, java.lang.String)
326: */
327: public void deleteFolder(String folder) throws Exception {
328: FolderDbObject foldObj = getInboxFolder();
329: if (foldObj.getId().toString().equals(folder)) {
330: // it is inbox and you can not delete INBOXin pop3 mode
331: throw new SystemException();
332: }
333:
334: IGenericDao dao = null;
335: try {
336: dao = org.claros.intouch.common.utility.Utility
337: .getTxnDbConnection();
338: String username = auth.getUsername();
339:
340: Long folderId = new Long(folder);
341: FolderDbObject fld = getFolder(folder);
342: if (!fld.getUsername().equals(auth.getUsername())) {
343: throw new NoPermissionException();
344: }
345:
346: String sql = "DELETE FROM MSG_DB_OBJECTS WHERE USERNAME=? AND FOLDER_ID = ?";
347: // delete the emails under folder
348: dao.executeUpdate(sql, new Object[] { username, folderId });
349:
350: sql = "DELETE FROM MSG_RULES WHERE USERNAME=? AND DESTINATION = ?";
351: // delete the filters targeting the deleted folder
352: dao.executeUpdate(sql, new Object[] { username, folderId });
353:
354: // delete the folder
355: dao.deleteByPrimaryKey(FolderDbObject.class, folderId);
356: dao.commit();
357:
358: } catch (Exception e) {
359: // dao.rollback();
360: // throw e;
361: } finally {
362: JdbcUtil.close(dao);
363: dao = null;
364: }
365: }
366:
367: /* (non-Javadoc)
368: * @see org.claros.groupware.webmail.controllers.FolderController#getHeadersByFolder(org.claros.commons.models.AuthProfile, java.lang.String)
369: */
370: public ArrayList getHeadersByFolder(String folder) throws Exception {
371: ArrayList headers = new ArrayList();
372:
373: FolderControllerFactory foldFact = new FolderControllerFactory(
374: auth, profile, handler);
375: FolderController folderCont = foldFact.getFolderController();
376: List mails = null;
377: FolderDbObject foldObj = folderCont.getInboxFolder();
378: if (foldObj.getId().toString().equals(folder)) {
379: // it is inbox so we fetch e-mail on the fly
380: ProtocolFactory factory = new ProtocolFactory(profile,
381: auth, handler);
382: Protocol protocol = factory.getProtocol(folder);
383: // protocol.disconnect();
384: // this.handler = protocol.connect(org.claros.commons.mail.utility.Constants.CONNECTION_READ_WRITE);
385:
386: mails = protocol.fetchAllHeaders();
387: if (mails != null) {
388: EmailHeader item = null;
389: EmailHeader header = null;
390:
391: for (int i = 0; i < mails.size(); i++) {
392: item = (EmailHeader) mails.get(i);
393:
394: try {
395: header = new EmailHeader();
396:
397: header.setMultipart((item.isMultipart()) ? true
398: : false);
399: header.setMessageId(item.getMessageId());
400: header.setFrom(item.getFrom());
401: header.setTo(item.getTo());
402: header.setCc(item.getCc());
403: header.setBcc(item.getBcc());
404: header.setDate(item.getDate());
405: header.setReplyTo(item.getReplyTo());
406: header.setSize(item.getSize());
407: header
408: .setSubject(org.claros.commons.utility.Utility
409: .updateTRChars(item
410: .getSubject()));
411: header.setUnread(Boolean.valueOf(false));
412:
413: // now set the human readables.
414: header.setDateShown(Formatter.formatDate(header
415: .getDate(), "dd.MM.yyyy HH:mm"));
416: header
417: .setFromShown(org.claros.commons.utility.Utility
418: .updateTRChars(org.claros.commons.mail.utility.Utility
419: .addressArrToString(header
420: .getFrom())));
421: header
422: .setToShown(org.claros.commons.mail.utility.Utility
423: .addressArrToString(header
424: .getTo()));
425: header
426: .setCcShown(org.claros.commons.mail.utility.Utility
427: .addressArrToString(header
428: .getCc()));
429: header
430: .setSizeShown(org.claros.commons.mail.utility.Utility
431: .sizeToHumanReadable(header
432: .getSize()));
433:
434: // it is time to add it to the arraylist
435: headers.add(header);
436: } catch (Exception e1) {
437: log
438: .error(
439: "Could not parse headers of e-mail. Message might be defuncted or illegal formatted.",
440: e1);
441: }
442: }
443: }
444: } else {
445: // it is a database folder
446: mails = getMailsByFolder(folder);
447: if (mails != null) {
448: MsgDbObject item = null;
449: byte bEmail[] = null;
450: Properties props = new Properties();
451: Session session = Session.getDefaultInstance(props);
452: EmailHeader header = null;
453:
454: for (int i = 0; i < mails.size(); i++) {
455: item = (MsgDbObject) mails.get(i);
456: bEmail = item.getEmail();
457:
458: ByteArrayInputStream bis = new ByteArrayInputStream(
459: bEmail);
460: MimeMessage msg = new MimeMessage(session, bis);
461:
462: try {
463: header = new EmailHeader();
464:
465: header.setMultipart((msg
466: .isMimeType("multipart/*")) ? true
467: : false);
468: header.setMessageId(item.getId().intValue());
469: header.setFrom(msg.getFrom());
470: header
471: .setTo(msg
472: .getRecipients(Message.RecipientType.TO));
473: header
474: .setCc(msg
475: .getRecipients(Message.RecipientType.CC));
476: header
477: .setBcc(msg
478: .getRecipients(Message.RecipientType.BCC));
479: header.setDate(msg.getSentDate());
480: header.setReplyTo(msg.getReplyTo());
481: header.setSize(item.getMsgSize().longValue());
482: header
483: .setSubject(org.claros.commons.utility.Utility
484: .updateTRChars(msg.getSubject()));
485: header.setUnread(item.getUnread());
486:
487: // now set the human readables.
488: header.setDateShown(Formatter.formatDate(header
489: .getDate(), "dd.MM.yyyy HH:mm"));
490: header
491: .setFromShown(org.claros.commons.utility.Utility
492: .updateTRChars(org.claros.commons.mail.utility.Utility
493: .addressArrToString(header
494: .getFrom())));
495: header
496: .setToShown(org.claros.commons.mail.utility.Utility
497: .addressArrToString(header
498: .getTo()));
499: header
500: .setCcShown(org.claros.commons.mail.utility.Utility
501: .addressArrToString(header
502: .getCc()));
503: header
504: .setSizeShown(org.claros.commons.mail.utility.Utility
505: .sizeToHumanReadable(header
506: .getSize()));
507:
508: // it is time to add it to the arraylist
509: headers.add(header);
510: } catch (MessagingException e1) {
511: log
512: .error(
513: "Could not parse headers of e-mail. Message might be defuncted or illegal formatted.",
514: e1);
515: } finally {
516: bis.close();
517: }
518: }
519: }
520: }
521:
522: return headers;
523: }
524:
525: /* (non-Javadoc)
526: * @see org.claros.groupware.webmail.controllers.FolderController#createDefaultFolders(org.claros.commons.models.AuthProfile)
527: */
528: public void createDefaultFolders() throws Exception {
529: if (getInboxFolder() == null) {
530: createFolder(new FolderDbObject(null, new Long(0), auth
531: .getUsername(),
532: org.claros.commons.mail.utility.Constants
533: .FOLDER_INBOX(profile),
534: Constants.FOLDER_TYPE_INBOX));
535: }
536: if (getJunkFolder() == null) {
537: createFolder(new FolderDbObject(null, new Long(0), auth
538: .getUsername(),
539: org.claros.commons.mail.utility.Constants
540: .FOLDER_JUNK(profile),
541: Constants.FOLDER_TYPE_JUNK));
542: }
543: if (getSentItems() == null) {
544: createFolder(new FolderDbObject(null, new Long(0), auth
545: .getUsername(),
546: org.claros.commons.mail.utility.Constants
547: .FOLDER_SENT(profile),
548: Constants.FOLDER_TYPE_SENT));
549: }
550: if (getTrashFolder() == null) {
551: createFolder(new FolderDbObject(null, new Long(0), auth
552: .getUsername(),
553: org.claros.commons.mail.utility.Constants
554: .FOLDER_TRASH(profile),
555: Constants.FOLDER_TYPE_TRASH));
556: }
557: if (getDraftsFolder() == null) {
558: createFolder(new FolderDbObject(null, new Long(0), auth
559: .getUsername(),
560: org.claros.commons.mail.utility.Constants
561: .FOLDER_DRAFTS(profile),
562: Constants.FOLDER_TYPE_DRAFTS));
563: }
564: }
565:
566: /* (non-Javadoc)
567: * @see org.claros.groupware.webmail.controllers.FolderController#renameFolder(java.lang.String, java.lang.String)
568: */
569: public void renameFolder(String oldName, String newName)
570: throws Exception {
571: if (oldName.equals(org.claros.commons.mail.utility.Constants
572: .FOLDER_INBOX(profile))) {
573: throw new SystemException();
574: }
575: List folders = getFolders();
576: FolderDbObjectWrapper tmp = null;
577: String n = null;
578: for (int i = 0; i < folders.size(); i++) {
579: tmp = (FolderDbObjectWrapper) folders.get(i);
580: n = tmp.getFolderName();
581: if (n.equals(oldName)) {
582:
583: IGenericDao dao = null;
584: try {
585: dao = org.claros.intouch.common.utility.Utility
586: .getDbConnection();
587:
588: FolderDbObject item = getFolder(tmp.getId()
589: .toString());
590: item.setFolderName(newName);
591:
592: dao.update(item);
593: } finally {
594: JdbcUtil.close(dao);
595: dao = null;
596: }
597: return;
598: }
599: }
600: throw new NoPermissionException();
601: }
602: }
|