001: /*
002: Copyright (C) 2005 Know Gate S.L. All rights reserved.
003: C/Oņa, 107 1š2 28050 Madrid (Spain)
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions
007: are met:
008:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011:
012: 2. The end-user documentation included with the redistribution,
013: if any, must include the following acknowledgment:
014: "This product includes software parts from hipergate
015: (http://www.hipergate.org/)."
016: Alternately, this acknowledgment may appear in the software itself,
017: if and wherever such third-party acknowledgments normally appear.
018:
019: 3. The name hipergate must not be used to endorse or promote products
020: derived from this software without prior written permission.
021: Products derived from this software may not be called hipergate,
022: nor may hipergate appear in their name, without prior written
023: permission.
024:
025: This library is distributed in the hope that it will be useful,
026: but WITHOUT ANY WARRANTY; without even the implied warranty of
027: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
028:
029: You should have received a copy of hipergate License with this code;
030: if not, visit http://www.hipergate.org or mail to info@hipergate.org
031: */
032:
033: package com.knowgate.hipermail;
034:
035: import java.sql.SQLException;
036: import java.sql.PreparedStatement;
037: import java.sql.ResultSet;
038: import java.sql.Statement;
039: import java.sql.CallableStatement;
040:
041: import java.io.IOException;
042:
043: import java.util.Properties;
044:
045: import com.knowgate.jdc.JDCConnection;
046: import com.knowgate.dataobjs.DB;
047: import com.knowgate.dataobjs.DBPersist;
048: import com.knowgate.dataobjs.DBSubset;
049: import com.knowgate.acl.ACLUser;
050: import com.knowgate.misc.Gadgets;
051: import com.knowgate.hipergate.Categories;
052: import com.knowgate.hipergate.Category;
053:
054: /**
055: * @author Sergio Montoro Ten
056: * @version 1.0
057: */
058:
059: public class MailAccount extends DBPersist {
060:
061: public MailAccount() {
062: super (DB.k_user_mail, "MailAccount");
063: }
064:
065: // ----------------------------------------------------------
066:
067: public MailAccount(JDCConnection oConn, String sGuAccount)
068: throws SQLException {
069: super (DB.k_user_mail, "MailAccount");
070: load(oConn, new Object[] { sGuAccount });
071: }
072:
073: // ----------------------------------------------------------
074:
075: /**
076: * <p>Store mail account</p>
077: * This method has a special side effect: only one mail account may be the
078: * default one for a given user. So each time that an account is stored with
079: * it bo_default flag set to 1 the other account for the same user are set to
080: * bo_default=0.<br>
081: * This method also calls Gadgets.checkEMail() on tx_main_email and tx_reply_mail
082: * if they do not have a valid syntax a SQLException is thrown
083: * @param oConn JDCConnection
084: * @return boolean
085: * @throws SQLException If tx_main_email or tx_reply_mail do not have a valid syntax
086: */
087: public boolean store(JDCConnection oConn) throws SQLException {
088: if (isNull(DB.gu_account)) {
089: put(DB.gu_account, Gadgets.generateUUID());
090: }
091: if (isNull(DB.bo_default)) {
092: replace(DB.bo_default, (short) 0);
093: }
094: if (isNull(DB.incoming_spa)) {
095: replace(DB.incoming_spa, (short) 0);
096: }
097: if (isNull(DB.incoming_ssl)) {
098: replace(DB.incoming_ssl, (short) 0);
099: }
100: if (isNull(DB.outgoing_spa)) {
101: replace(DB.outgoing_spa, (short) 0);
102: }
103: if (isNull(DB.outgoing_ssl)) {
104: replace(DB.outgoing_ssl, (short) 0);
105: }
106: if (!isNull(DB.tx_main_email)) {
107: if (!Gadgets.checkEMail(getString(DB.tx_main_email)))
108: throw new SQLException(
109: "Mail account " + getString(DB.tx_main_email)
110: + " is not valid", "23000");
111: }
112: if (!isNull(DB.tx_reply_email)) {
113: if (!Gadgets.checkEMail(getString(DB.tx_reply_email)))
114: throw new SQLException("Mail account "
115: + getString(DB.tx_reply_email)
116: + " is not valid", "23000");
117: }
118: if (!isNull(DB.bo_default)) {
119: if (getShort(DB.bo_default) == (short) 1) {
120: PreparedStatement oStmt = oConn
121: .prepareStatement("UPDATE " + DB.k_user_mail
122: + " SET " + DB.bo_default + "=0 WHERE "
123: + DB.gu_user + "=?");
124: oStmt.setString(1, getStringNull(DB.gu_user, null));
125: oStmt.executeUpdate();
126: oStmt.close();
127: }
128: }
129: return super .store(oConn);
130: } // store
131:
132: // ----------------------------------------------------------
133:
134: public Properties getProperties() {
135: Properties oProps = new Properties();
136: oProps.put("mail.store.protocol", getStringNull(
137: DB.incoming_protocol, "pop3"));
138: oProps.put("mail.transport.protocol", getStringNull(
139: DB.outgoing_protocol, "smtp"));
140: oProps.put("mail.incoming", getStringNull(DB.incoming_server,
141: "localhost"));
142: oProps.put("mail.outgoing", getStringNull(DB.outgoing_server,
143: "localhost"));
144: if (isNull(DB.incoming_port))
145: oProps.put("mail.pop3.port", "110");
146: else
147: oProps.put("mail." + getString(DB.incoming_protocol)
148: + ".port", String
149: .valueOf(getShort(DB.incoming_port)));
150: if (isNull(DB.outgoing_port))
151: oProps.put("mail.smtp.port", "25");
152: else
153: oProps.put("mail." + getString(DB.outgoing_protocol)
154: + ".port", String
155: .valueOf(getShort(DB.outgoing_port)));
156: return oProps;
157: }
158:
159: // ----------------------------------------------------------
160:
161: public void setProperties(Properties oProps) {
162: replace(DB.incoming_protocol, oProps.getProperty(
163: "mail.store.protocol", "pop3"));
164: replace(DB.outgoing_protocol, oProps.getProperty(
165: "mail.transport.protocol", "smtp"));
166: replace(DB.incoming_server, oProps.getProperty("mail."
167: + getString(DB.incoming_protocol) + ".host", oProps
168: .getProperty("mail.incoming", "localhost")));
169: replace(DB.outgoing_server, oProps.getProperty("mail."
170: + getString(DB.outgoing_protocol) + ".host", oProps
171: .getProperty("mail.outgoing", "localhost")));
172: replace(DB.incoming_port, oProps.getProperty("mail."
173: + getString(DB.incoming_protocol) + ".port", "110"));
174: replace(DB.outgoing_port, oProps.getProperty("mail."
175: + getString(DB.outgoing_protocol) + ".port", "25"));
176: }
177:
178: // **********************************************************
179: // Static Methods
180:
181: /**
182: * <p>Get MailAccount for ACLUser</p>
183: * Get the default mail account for an ACLUser or the first account if there is no default.
184: * @param oConn JDCConnection
185: * @param sGuUser String ACLUser GUID (from k_users.gu_user)
186: * @return MailAccount instance or <b>null</b> if there are no mail accounts for the given user
187: * @throws SQLException
188: */
189: public static MailAccount forUser(JDCConnection oConn,
190: String sGuUser) throws SQLException {
191: String sGuAccount;
192: PreparedStatement oStmt;
193: ResultSet oRSet;
194: MailAccount oRetVal;
195: oStmt = oConn.prepareStatement("SELECT " + DB.gu_account
196: + " FROM " + DB.k_user_mail + " WHERE " + DB.gu_user
197: + "=? AND " + DB.bo_default + "=?");
198: oStmt.setString(1, sGuUser);
199: oStmt.setShort(2, (short) 1);
200: oRSet = oStmt.executeQuery();
201: if (oRSet.next())
202: sGuAccount = oRSet.getString(1);
203: else
204: sGuAccount = null;
205: oRSet.close();
206: oStmt.close();
207: if (null == sGuAccount) {
208: oStmt = oConn.prepareStatement("SELECT " + DB.gu_account
209: + " FROM " + DB.k_user_mail + " WHERE "
210: + DB.gu_user + "=?");
211: oStmt.setString(1, sGuUser);
212: oRSet = oStmt.executeQuery();
213: if (oRSet.next())
214: sGuAccount = oRSet.getString(1);
215: oRSet.close();
216: oStmt.close();
217: }
218: if (null == sGuAccount) {
219: oRetVal = null;
220: } else {
221: oRetVal = new MailAccount();
222: oRetVal.load(oConn, new Object[] { sGuAccount });
223: }
224: return oRetVal;
225: } // forUser
226:
227: /**
228: * <p>Get MailAccount for ACLUser or create a default one</p>
229: * If no account for given user is found at k_user_mail then one is temporaly
230: * created by using properties given at parameter oProps and taking user's
231: * tx_main_email and tx_pwd as mail address and password.
232: * @param oConn JDCConnection
233: * @param sGuUser String ACLUser GUID (from k_users.gu_user)
234: * @param oProps Properties usually take from an hipergate.cnf file by calling
235: * Environment.getProfile("hipergate")
236: * @return MailAccount instance or <b>null</b> if there are no user with the given GUID
237: * @throws SQLException
238: */
239: public static MailAccount forUser(JDCConnection oConn,
240: String sGuUser, Properties oProps) throws SQLException {
241: MailAccount oRetVal = MailAccount.forUser(oConn, sGuUser);
242: if (null == oRetVal) {
243: ACLUser oUser = new ACLUser();
244: if (oUser.load(oConn, new Object[] { sGuUser })) {
245: oRetVal = new MailAccount();
246: oRetVal.setProperties(oProps);
247: oRetVal.put(DB.gu_user, oUser.getString(DB.gu_user));
248: oRetVal.put(DB.tl_account, "Default account for "
249: + oUser.getString(DB.tx_nickname));
250: oRetVal.put(DB.bo_default, (short) 1);
251: oRetVal.put(DB.bo_synchronize, (short) 0);
252: oRetVal.put(DB.tx_main_email, oUser
253: .getString(DB.tx_main_email));
254: oRetVal.put(DB.tx_reply_email, oUser
255: .getString(DB.tx_main_email));
256: oRetVal.put(DB.incoming_password, oUser
257: .getString(DB.tx_pwd));
258: oRetVal.put(DB.outgoing_password, oUser
259: .getString(DB.tx_pwd));
260: }
261: }
262: return oRetVal;
263: }
264:
265: private static void deleteCategorySet(JDCConnection oConn,
266: DBSubset oCatgSet) throws SQLException, IOException {
267: final int iSize = oCatgSet.getRowCount();
268: // Delete recursively children categories first
269: for (int c = 0; c < iSize; c++) {
270: DBSubset oChildCatgs = new DBSubset(DB.k_cat_tree,
271: DB.gu_child_cat, DB.gu_parent_cat + "=?", 10);
272: oChildCatgs.load(oConn, new Object[] { oCatgSet.getString(
273: 0, c) });
274: deleteCategorySet(oConn, oChildCatgs);
275: }
276: // Deleting the category will delete the associated MimeMessages, but it is faster to do it first
277: // for avoiding lots of calls to MimeMessage.delete() method
278: for (int d = 0; d < iSize; d++) {
279: DBSubset oDeleted = new DBSubset(DB.k_mime_msgs,
280: DB.gu_mimemsg, DB.gu_category + "=?", 100);
281: oDeleted.load(oConn, new Object[] { oCatgSet
282: .getString(0, d) });
283: final int iDeleted = oDeleted.getRowCount();
284: if (oConn.getDataBaseProduct() == JDCConnection.DBMS_POSTGRESQL) {
285: Statement oStmt = oConn.createStatement();
286: for (int m = 0; m < iDeleted; m++) {
287: oStmt.executeQuery("SELECT k_sp_del_mime_msg('"
288: + oDeleted.getString(0, m) + "')");
289: } // next (message)
290: oStmt.close();
291: oStmt = null;
292: } else {
293: CallableStatement oCall = oConn
294: .prepareCall("{ call k_sp_del_mime_msg(?) }");
295: for (int m = 0; m < iDeleted; m++) {
296: oCall.setString(1, oDeleted.getString(0, m));
297: oCall.execute();
298: } // next
299: oCall.close();
300: oCall = null;
301: } // fi
302: // When the Category is deleted its associated Products are erased from disk.
303: // As the MBOX files are stored as products of the category, the MBOX files
304: // will be deleted as a side effect of deleting the Category
305: Category.delete(oConn, oCatgSet.getString(0, d));
306: } // next (category)
307: } // deleteCategorySet
308:
309: public boolean delete(JDCConnection oConn) throws SQLException {
310: ACLUser oUsr = new ACLUser(getString(DB.gu_user));
311: Category oRootCat = new Category(oConn, oUsr.getMailRoot(oConn));
312: DBSubset oMailFoldersCatgs = new DBSubset(DB.k_cat_tree,
313: DB.gu_child_cat, DB.gu_parent_cat + "=?", 10);
314: oMailFoldersCatgs.load(oConn, new Object[] { oRootCat
315: .getString(DB.gu_category) });
316: try {
317: deleteCategorySet(oConn, oMailFoldersCatgs);
318: } catch (IOException ioe) {
319: throw new SQLException(ioe.getMessage());
320: }
321: return super .delete(oConn);
322: } // delete
323:
324: public static boolean delete(JDCConnection oConn, String sGuAccount)
325: throws SQLException, IOException {
326: boolean bRetVal;
327: MailAccount oAcc = new MailAccount();
328: if (oAcc.load(oConn, new Object[] { sGuAccount })) {
329: bRetVal = oAcc.delete(oConn);
330: } else {
331: bRetVal = false;
332: }
333: return bRetVal;
334: } // delete
335:
336: // **********************************************************
337: // Public Constants
338:
339: public static final short ClassId = 810;
340:
341: }
|