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.models.MsgDbObject;
032: import org.claros.intouch.webmail.models.FolderDbObject;
033: import org.claros.intouch.webmail.models.FolderDbObjectWrapper;
034:
035: import com.jenkov.mrpersister.impl.mapping.AutoGeneratedColumnsMapper;
036: import com.jenkov.mrpersister.itf.IGenericDao;
037: import com.jenkov.mrpersister.itf.mapping.IObjectMappingKey;
038: import com.jenkov.mrpersister.util.JdbcUtil;
039:
040: /**
041: * @author Umut Gokbayrak
042: */
043: public class DbFolderControllerImpl implements FolderController {
044: private static Log log = LogFactory
045: .getLog(DbFolderControllerImpl.class);
046: private AuthProfile auth;
047: private ConnectionProfile profile;
048: private ConnectionMetaHandler handler;
049:
050: /**
051: * @param auth
052: */
053: public DbFolderControllerImpl(AuthProfile auth,
054: ConnectionProfile profile, ConnectionMetaHandler handler) {
055: this .auth = auth;
056: this .profile = profile;
057: this .handler = handler;
058: }
059:
060: /**
061: * used to disable it.
062: *
063: */
064: @SuppressWarnings("unused")
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: @SuppressWarnings("deprecation")
219: public void createFolder(FolderDbObject item) throws Exception {
220: IGenericDao dao = null;
221: try {
222: dao = Utility.getDbConnection();
223:
224: IObjectMappingKey myObj = org.claros.intouch.common.utility.Constants.persistMan
225: .getObjectMappingFactory().createInstance(
226: FolderDbObject.class,
227: new AutoGeneratedColumnsMapper(true));
228: dao.insert(myObj, item);
229: } finally {
230: JdbcUtil.close(dao);
231: dao = null;
232: }
233: }
234:
235: /* (non-Javadoc)
236: * @see org.claros.groupware.webmail.controllers.FolderController#countUnreadMessages(org.claros.commons.models.AuthProfile, java.lang.Long)
237: */
238: public Integer countUnreadMessages(String folder) throws Exception {
239: FolderDbObject foldObj = getInboxFolder();
240: if (foldObj.getId().toString().equals(folder)) {
241: // it is the INBOX
242: ProtocolFactory pFact = new ProtocolFactory(profile, auth,
243: handler);
244: Protocol prot = pFact.getPop3();
245: return new Integer(prot.getTotalMessageCount());
246: } else {
247: QueryRunner run = new QueryRunner(DbConfigList
248: .getDataSourceById("file"));
249: HashMap result = null;
250: String username = auth.getUsername();
251: try {
252: Long folderId = new Long(folder);
253: String sql = "SELECT COUNT(*) AS NUMBER FROM MSG_DB_OBJECTS WHERE USERNAME=? AND FOLDER_ID = ? AND UNREAD = ?";
254: result = (HashMap) run.query(sql, new Object[] {
255: username, folderId, new Boolean(true) },
256: new MapHandler());
257: } catch (SQLException e) {
258: return new Integer(0);
259: }
260: if (result != null) {
261: return new Integer(result.get("number").toString());
262: }
263: }
264: return new Integer(0);
265: }
266:
267: /* (non-Javadoc)
268: * @see org.claros.groupware.webmail.controllers.FolderController#countTotalMessages(org.claros.commons.models.AuthProfile, java.lang.String)
269: */
270: public Integer countTotalMessages(String folder) throws Exception {
271: FolderDbObject foldObj = getInboxFolder();
272: if (foldObj.getId().toString().equals(folder)) {
273: // it is the INBOX
274: ProtocolFactory pFact = new ProtocolFactory(profile, auth,
275: handler);
276: Protocol prot = pFact.getPop3();
277: return new Integer(prot.getTotalMessageCount());
278: } else {
279: // it is a database folder
280: QueryRunner run = new QueryRunner(DbConfigList
281: .getDataSourceById("file"));
282: HashMap result = null;
283: String username = auth.getUsername();
284: try {
285: Long folderId = new Long(folder);
286: String sql = "SELECT COUNT(*) AS NUMBER FROM MSG_DB_OBJECTS WHERE USERNAME=? AND FOLDER_ID = ? ";
287: result = (HashMap) run.query(sql, new Object[] {
288: username, folderId }, new MapHandler());
289: } catch (SQLException e) {
290: return new Integer(0);
291: }
292: if (result != null) {
293: return new Integer(result.get("number").toString());
294: }
295: }
296: return new Integer(0);
297: }
298:
299: /* (non-Javadoc)
300: * @see org.claros.groupware.webmail.controllers.FolderController#emptyFolder(org.claros.commons.models.AuthProfile, java.lang.String)
301: */
302: public void emptyFolder(String folder) throws Exception {
303: FolderDbObject foldObj = getInboxFolder();
304: if (foldObj.getId().toString().equals(folder)) {
305: // it is the INBOX
306: ProtocolFactory pFact = new ProtocolFactory(profile, auth,
307: handler);
308: Protocol prot = pFact.getPop3();
309: prot.emptyFolder();
310: } else {
311: // it is a database folder
312: QueryRunner run = new QueryRunner(DbConfigList
313: .getDataSourceById("file"));
314: String username = auth.getUsername();
315: try {
316: Long folderId = new Long(folder);
317: String sql = "DELETE FROM MSG_DB_OBJECTS WHERE USERNAME=? AND FOLDER_ID=?";
318: run.update(sql, new Object[] { username, folderId });
319: } catch (SQLException e) {
320: throw e;
321: }
322: }
323: }
324:
325: /* (non-Javadoc)
326: * @see org.claros.groupware.webmail.controllers.FolderController#deleteFolder(org.claros.commons.models.AuthProfile, java.lang.String)
327: */
328: public void deleteFolder(String folder) throws Exception {
329: FolderDbObject foldObj = getInboxFolder();
330: if (foldObj.getId().toString().equals(folder)) {
331: // it is inbox and you can not delete INBOXin pop3 mode
332: throw new SystemException();
333: }
334:
335: IGenericDao dao = null;
336: try {
337: dao = org.claros.intouch.common.utility.Utility
338: .getTxnDbConnection();
339: String username = auth.getUsername();
340:
341: Long folderId = new Long(folder);
342: FolderDbObject fld = getFolder(folder);
343: if (!fld.getUsername().equals(auth.getUsername())) {
344: throw new NoPermissionException();
345: }
346:
347: String sql = "DELETE FROM MSG_DB_OBJECTS WHERE USERNAME=? AND FOLDER_ID = ?";
348: // delete the emails under folder
349: dao.executeUpdate(sql, new Object[] { username, folderId });
350:
351: sql = "DELETE FROM MSG_RULES WHERE USERNAME=? AND DESTINATION = ?";
352: // delete the filters targeting the deleted folder
353: dao.executeUpdate(sql, new Object[] { username, folderId });
354:
355: // delete the folder
356: dao.deleteByPrimaryKey(FolderDbObject.class, folderId);
357: dao.commit();
358:
359: } catch (Exception e) {
360: // dao.rollback();
361: // throw e;
362: } finally {
363: JdbcUtil.close(dao);
364: dao = null;
365: }
366: }
367:
368: /* (non-Javadoc)
369: * @see org.claros.groupware.webmail.controllers.FolderController#getHeadersByFolder(org.claros.commons.models.AuthProfile, java.lang.String)
370: */
371: public ArrayList getHeadersByFolder(String folder) throws Exception {
372: ArrayList headers = new ArrayList();
373:
374: List mails = null;
375:
376: if (org.claros.commons.mail.utility.Constants
377: .FOLDER_INBOX(null).equals(folder)) {
378: // it is inbox so we fetch e-mail on the fly
379: ProtocolFactory factory = new ProtocolFactory(profile,
380: auth, handler);
381: Protocol protocol = factory.getProtocol(folder);
382: // protocol.disconnect();
383: // this.handler = protocol.connect(org.claros.commons.mail.utility.Constants.CONNECTION_READ_WRITE);
384:
385: mails = protocol.fetchAllHeaders();
386: if (mails != null) {
387: EmailHeader item = null;
388: EmailHeader header = null;
389:
390: for (int i = 0; i < mails.size(); i++) {
391: item = (EmailHeader) mails.get(i);
392:
393: try {
394: header = new EmailHeader();
395:
396: header.setMultipart((item.isMultipart()) ? true
397: : false);
398: header.setMessageId(item.getMessageId());
399: header.setFrom(item.getFrom());
400: header.setTo(item.getTo());
401: header.setCc(item.getCc());
402: header.setBcc(item.getBcc());
403: header.setDate(item.getDate());
404: header.setReplyTo(item.getReplyTo());
405: header.setSize(item.getSize());
406: header
407: .setSubject(org.claros.commons.utility.Utility
408: .updateTRChars(item
409: .getSubject()));
410: header.setUnread(Boolean.valueOf(false));
411:
412: // now set the human readables.
413: header.setDateShown(Formatter.formatDate(header
414: .getDate(), "dd.MM.yyyy HH:mm"));
415: header
416: .setFromShown(org.claros.commons.utility.Utility
417: .updateTRChars(org.claros.commons.mail.utility.Utility
418: .addressArrToString(header
419: .getFrom())));
420: header
421: .setToShown(org.claros.commons.mail.utility.Utility
422: .addressArrToString(header
423: .getTo()));
424: header
425: .setCcShown(org.claros.commons.mail.utility.Utility
426: .addressArrToString(header
427: .getCc()));
428: header
429: .setSizeShown(org.claros.commons.mail.utility.Utility
430: .sizeToHumanReadable(header
431: .getSize()));
432:
433: // it is time to add it to the arraylist
434: headers.add(header);
435: } catch (Exception e1) {
436: log
437: .error(
438: "Could not parse headers of e-mail. Message might be defuncted or illegal formatted.",
439: e1);
440: }
441: }
442: }
443: } else {
444: // it is a database folder
445: mails = getMailsByFolder(folder);
446: if (mails != null) {
447: MsgDbObject item = null;
448: byte bEmail[] = null;
449: Properties props = new Properties();
450: Session session = Session.getDefaultInstance(props);
451: EmailHeader header = null;
452:
453: for (int i = 0; i < mails.size(); i++) {
454: item = (MsgDbObject) mails.get(i);
455: bEmail = item.getEmail();
456:
457: ByteArrayInputStream bis = new ByteArrayInputStream(
458: bEmail);
459: MimeMessage msg = new MimeMessage(session, bis);
460:
461: try {
462: header = new EmailHeader();
463:
464: header.setMultipart((msg
465: .isMimeType("multipart/*")) ? true
466: : false);
467: header.setMessageId(item.getId().intValue());
468: header.setFrom(msg.getFrom());
469: header
470: .setTo(msg
471: .getRecipients(Message.RecipientType.TO));
472: header
473: .setCc(msg
474: .getRecipients(Message.RecipientType.CC));
475: header
476: .setBcc(msg
477: .getRecipients(Message.RecipientType.BCC));
478: header.setDate(msg.getSentDate());
479: header.setReplyTo(msg.getReplyTo());
480: header.setSize(item.getMsgSize().longValue());
481: header
482: .setSubject(org.claros.commons.utility.Utility
483: .updateTRChars(msg.getSubject()));
484: header.setUnread(item.getUnread());
485:
486: // now set the human readables.
487: header.setDateShown(Formatter.formatDate(header
488: .getDate(), "dd.MM.yyyy HH:mm"));
489: header
490: .setFromShown(org.claros.commons.utility.Utility
491: .updateTRChars(org.claros.commons.mail.utility.Utility
492: .addressArrToString(header
493: .getFrom())));
494: header
495: .setToShown(org.claros.commons.mail.utility.Utility
496: .addressArrToString(header
497: .getTo()));
498: header
499: .setCcShown(org.claros.commons.mail.utility.Utility
500: .addressArrToString(header
501: .getCc()));
502: header
503: .setSizeShown(org.claros.commons.mail.utility.Utility
504: .sizeToHumanReadable(header
505: .getSize()));
506:
507: // it is time to add it to the arraylist
508: headers.add(header);
509: } catch (MessagingException e1) {
510: log
511: .error(
512: "Could not parse headers of e-mail. Message might be defuncted or illegal formatted.",
513: e1);
514: } finally {
515: bis.close();
516: }
517: }
518: }
519: }
520:
521: return headers;
522: }
523:
524: /* (non-Javadoc)
525: * @see org.claros.groupware.webmail.controllers.FolderController#createDefaultFolders(org.claros.commons.models.AuthProfile)
526: */
527: public void createDefaultFolders() throws Exception {
528: if (getInboxFolder() == null) {
529: createFolder(new FolderDbObject(null, new Long(0), auth
530: .getUsername(),
531: org.claros.commons.mail.utility.Constants
532: .FOLDER_INBOX(profile),
533: Constants.FOLDER_TYPE_INBOX));
534: }
535: if (getJunkFolder() == null) {
536: createFolder(new FolderDbObject(null, new Long(0), auth
537: .getUsername(),
538: org.claros.commons.mail.utility.Constants
539: .FOLDER_JUNK(profile),
540: Constants.FOLDER_TYPE_JUNK));
541: }
542: if (getSentItems() == null) {
543: createFolder(new FolderDbObject(null, new Long(0), auth
544: .getUsername(),
545: org.claros.commons.mail.utility.Constants
546: .FOLDER_SENT(profile),
547: Constants.FOLDER_TYPE_SENT));
548: }
549: if (getTrashFolder() == null) {
550: createFolder(new FolderDbObject(null, new Long(0), auth
551: .getUsername(),
552: org.claros.commons.mail.utility.Constants
553: .FOLDER_TRASH(profile),
554: Constants.FOLDER_TYPE_TRASH));
555: }
556: if (getDraftsFolder() == null) {
557: createFolder(new FolderDbObject(null, new Long(0), auth
558: .getUsername(),
559: org.claros.commons.mail.utility.Constants
560: .FOLDER_DRAFTS(profile),
561: Constants.FOLDER_TYPE_DRAFTS));
562: }
563: }
564:
565: /* (non-Javadoc)
566: * @see org.claros.groupware.webmail.controllers.FolderController#renameFolder(java.lang.String, java.lang.String)
567: */
568: public void renameFolder(String oldName, String newName)
569: throws Exception {
570: if (oldName.equals(org.claros.commons.mail.utility.Constants
571: .FOLDER_INBOX(profile))) {
572: throw new SystemException();
573: }
574: List folders = getFolders();
575: FolderDbObjectWrapper tmp = null;
576: String n = null;
577: for (int i = 0; i < folders.size(); i++) {
578: tmp = (FolderDbObjectWrapper) folders.get(i);
579: n = tmp.getFolderName();
580: if (n.equals(oldName)) {
581:
582: IGenericDao dao = null;
583: try {
584: dao = org.claros.intouch.common.utility.Utility
585: .getDbConnection();
586:
587: FolderDbObject item = getFolder(tmp.getId()
588: .toString());
589: item.setFolderName(newName);
590:
591: dao.update(item);
592: } finally {
593: JdbcUtil.close(dao);
594: dao = null;
595: }
596: return;
597: }
598: }
599: throw new NoPermissionException();
600: }
601:
602: /**
603: *
604: */
605: public List getHeadersByFolder(String folder, int[] msgs)
606: throws Exception {
607: ArrayList result = new ArrayList();
608: List headers = getHeadersByFolder(folder);
609: EmailHeader tmp = null;
610: for (int i = 0; i < headers.size(); i++) {
611: tmp = (EmailHeader) headers.get(i);
612: for (int j = 0; j < msgs.length; j++) {
613: if (tmp.getMessageId() == msgs[j]) {
614: result.add(tmp);
615: break;
616: }
617: }
618: }
619: return result;
620: }
621: }
|