001: package org.claros.intouch.calendar.controllers;
002:
003: import java.io.BufferedInputStream;
004: import java.io.File;
005: import java.io.FileInputStream;
006: import java.io.FileOutputStream;
007: import java.sql.Timestamp;
008: import java.text.DecimalFormat;
009: import java.text.SimpleDateFormat;
010: import java.util.ArrayList;
011: import java.util.Date;
012: import java.util.HashMap;
013: import java.util.List;
014: import java.util.Locale;
015: import java.util.Set;
016:
017: import javax.activation.DataHandler;
018: import javax.activation.DataSource;
019: import javax.mail.Address;
020: import javax.mail.internet.InternetAddress;
021: import javax.mail.internet.MimeBodyPart;
022:
023: import net.fortuna.ical4j.data.CalendarOutputter;
024: import net.fortuna.ical4j.model.Calendar;
025: import net.fortuna.ical4j.model.ComponentList;
026: import net.fortuna.ical4j.model.PropertyList;
027: import net.fortuna.ical4j.model.component.VEvent;
028: import net.fortuna.ical4j.model.property.CalScale;
029: import net.fortuna.ical4j.model.property.Method;
030: import net.fortuna.ical4j.model.property.ProdId;
031: import net.fortuna.ical4j.model.property.Uid;
032: import net.fortuna.ical4j.model.property.Version;
033:
034: import org.apache.commons.configuration.Configuration;
035: import org.apache.commons.configuration.ConfigurationException;
036: import org.apache.commons.configuration.PropertiesConfiguration;
037: import org.claros.commons.auth.models.AuthProfile;
038: import org.claros.commons.configuration.Paths;
039: import org.claros.commons.configuration.PropertyFile;
040: import org.claros.commons.exception.SystemException;
041: import org.claros.commons.mail.models.ByteArrayDataSource;
042: import org.claros.commons.mail.models.ConnectionProfile;
043: import org.claros.commons.mail.models.ConnectionProfileList;
044: import org.claros.commons.mail.models.Email;
045: import org.claros.commons.mail.models.EmailHeader;
046: import org.claros.commons.mail.models.EmailPart;
047: import org.claros.commons.mail.protocols.Smtp;
048: import org.claros.commons.mail.utility.Utility;
049: import org.claros.commons.utility.MD5;
050: import org.claros.intouch.calendar.models.CalendarObject;
051: import org.claros.intouch.calendar.models.CalendarObjectWrap;
052: import org.claros.intouch.preferences.controllers.UserPrefsController;
053:
054: public class CheckAlertBatchThread extends Thread {
055: private static DecimalFormat df = new DecimalFormat("00");
056:
057: public void run() {
058: while (true) {
059: try {
060: List alerts = CalendarController.getAlertsForAll(null);
061: if (alerts != null && alerts.size() > 0) {
062: CalendarObjectWrap tmp = null;
063:
064: String monYear = null;
065: for (int i = 0; i < alerts.size(); i++) {
066: tmp = (CalendarObjectWrap) alerts.get(i);
067:
068: try {
069: // we only parse the e-mail(and other) reminders not the popup ones.
070: if (tmp.getReminderMethod().intValue() == 2) {
071: String username = tmp.getUsername();
072: AuthProfile auth = new AuthProfile();
073: auth.setUsername(username);
074:
075: // get user's e-mail address, cause we'll be sending e-mail to him/her
076: String email = UserPrefsController
077: .getUserSetting(auth,
078: "emailAddress");
079: if (email != null
080: && !email.trim().equals("")
081: && email.indexOf("@") > 1) {
082: Calendar calendar = new Calendar();
083: PropertyList props1 = calendar
084: .getProperties();
085: props1.add(new ProdId(
086: "-//Claros//inTouch2//EN"));
087: props1.add(Version.VERSION_2_0);
088: props1.add(CalScale.GREGORIAN);
089: props1.add(Method.PUBLISH);
090:
091: //PropertyList props = new PropertyList();
092: java.util.Calendar calTmp2 = java.util.Calendar
093: .getInstance();
094: java.util.Calendar calTmp = java.util.Calendar
095: .getInstance();
096:
097: calTmp.setTimeInMillis(tmp
098: .getEndDate().getTime());
099: calTmp2.setTimeInMillis(tmp
100: .getOccuringDate()
101: .getTime());
102:
103: monYear = calTmp2
104: .get(java.util.Calendar.YEAR)
105: + "-"
106: + df
107: .format(calTmp2
108: .get(java.util.Calendar.MONTH) + 1)
109: + "-"
110: + df
111: .format(calTmp2
112: .get(java.util.Calendar.DATE));
113: Timestamp start = Timestamp
114: .valueOf(monYear
115: + " "
116: + df
117: .format(calTmp2
118: .get(java.util.Calendar.HOUR_OF_DAY))
119: + ":"
120: + df
121: .format(calTmp2
122: .get(java.util.Calendar.MINUTE))
123: + ":00.000");
124: Timestamp end = Timestamp
125: .valueOf(monYear
126: + " "
127: + df
128: .format(calTmp
129: .get(java.util.Calendar.HOUR_OF_DAY))
130: + ":"
131: + df
132: .format(calTmp
133: .get(java.util.Calendar.MINUTE))
134: + ":00.000");
135:
136: /*
137: props.add(new DtStart(new DateTime(new Date(start.getTime()))));
138: props.add(new DtEnd(new DateTime(new Date(end.getTime()))));
139: props.add(new DtStamp(new DateTime(new Date())));
140: props.add(new Summary(tmp.getDescription()));
141: props.add(new Location(tmp.getLocation()));
142: props.add(new Trigger(new DateTime(new Date(start.getTime()))));
143: props.add(new Created(new DateTime(new Date())));
144: */
145:
146: ComponentList comps = calendar
147: .getComponents();
148: VEvent ev = new VEvent(
149: new net.fortuna.ical4j.model.Date(
150: start.getTime()),
151: new net.fortuna.ical4j.model.Date(
152: end.getTime()), tmp
153: .getDescription());
154: ev
155: .getProperties()
156: .add(
157: new Uid(
158: MD5
159: .getHashString(username
160: + Math
161: .random())
162: + "@claros.org"));
163: comps.add(ev);
164:
165: /*
166: int recur = tmp.getRepeatType().intValue();
167: switch (recur) {
168: case Constants.REPEAT_TYPE_ONCE:
169: break;
170: case Constants.REPEAT_TYPE_DAY:
171: props.add(new Recur(Recur.DAILY));
172: break;
173: case Constants.REPEAT_TYPE_MONTH:
174: props.add(new Recur(Recur.MONTHLY));
175: break;
176: case Constants.REPEAT_TYPE_WEEK:
177: props.add(new Recur(Recur.WEEKLY));
178: break;
179: case Constants.REPEAT_TYPE_YEAR:
180: props.add(new Recur(Recur.YEARLY));
181: break;
182: }
183: */
184:
185: String fileName = org.claros.intouch.common.utility.Constants.tmpDir
186: + "/"
187: + MD5
188: .getHashString(username
189: + Math
190: .random())
191: + ".ics";
192: FileOutputStream fout = new FileOutputStream(
193: fileName);
194: CalendarOutputter outputter = new CalendarOutputter();
195: outputter.output(calendar, fout);
196: fout.close();
197:
198: sendMail(tmp, auth.getUsername(),
199: email, start, end, fileName);
200:
201: }
202: }
203: } catch (Exception e) {
204: e.printStackTrace();
205: }
206: }
207: }
208: } catch (Throwable e) {
209: e.printStackTrace();
210: } finally {
211: try {
212: Thread.sleep(300000);
213: } catch (InterruptedException e) {
214: }
215: }
216: }
217: }
218:
219: private static String fromName;
220: private static String fromAddr;
221: private static String fromUsername;
222: private static String fromPassword;
223: private static String lang;
224: private static ConnectionProfile connProfile;
225: static {
226: try {
227: fromName = PropertyFile.getConfiguration(
228: "/config/config.xml").getString(
229: "calendar-smtp.mail-from-name");
230: fromAddr = PropertyFile.getConfiguration(
231: "/config/config.xml").getString(
232: "calendar-smtp.mail-from-address");
233: fromUsername = PropertyFile.getConfiguration(
234: "/config/config.xml").getString(
235: "calendar-smtp.username");
236: fromPassword = PropertyFile.getConfiguration(
237: "/config/config.xml").getString(
238: "calendar-smtp.password");
239: lang = PropertyFile.getConfiguration("/config/config.xml")
240: .getString("calendar-smtp.default-lang");
241:
242: HashMap map = ConnectionProfileList.getConList();
243: if (map != null) {
244: Set set = map.keySet();
245: if (set == null) {
246: throw new SystemException();
247: }
248: Object arr[] = set.toArray();
249: if (arr == null || arr.length <= 0) {
250: throw new SystemException();
251: }
252: connProfile = ConnectionProfileList
253: .getProfileByShortName((String) arr[0]);
254: }
255: } catch (Exception e) {
256: e.printStackTrace();
257: }
258: }
259:
260: private void sendMail(CalendarObjectWrap obj, String toUsername,
261: String to, Timestamp start, Timestamp end,
262: String icsFileName) throws Exception {
263: String from = "";
264: if (fromName != null && fromName.trim().length() > 0) {
265: from = fromName + "<" + fromAddr + ">";
266: }
267: // learn the global charset setting.
268:
269: // learn user preferences from the DB.
270: AuthProfile auth = new AuthProfile();
271: auth.setPassword(fromPassword);
272: auth.setUsername(fromUsername);
273:
274: // now create a new email object.
275: Email email = new Email();
276: EmailHeader header = new EmailHeader();
277:
278: Address adrs[] = Utility.stringToAddressArray(from);
279: header.setFrom(adrs);
280:
281: Address tos[] = Utility.stringToAddressArray(to);
282: header.setTo(tos);
283:
284: header.setSubject(getText("calendar") + ":"
285: + formatDate(obj.getOccuringDate()));
286: header.setDate(new Date());
287:
288: String replyTo = "noreply@"
289: + fromAddr.substring(fromAddr.indexOf("@") + 1);
290: if (replyTo != null && replyTo.trim().length() != 0) {
291: header.setReplyTo(new Address[] { new InternetAddress(
292: replyTo) });
293: }
294: email.setBaseHeader(header);
295:
296: ArrayList parts = new ArrayList();
297: EmailPart bodyPart = new EmailPart();
298: bodyPart.setContentType("text/html; charset=UTF-8");
299:
300: String body = "<strong>" + obj.getDescription()
301: + "</strong><br/><br/>" + getText("duration") + ": "
302: + formatDate(start) + " - " + formatDate(end) + "<br/>"
303: + getText("location") + ": " + obj.getLocation();
304: bodyPart.setContent(body);
305: parts.add(0, bodyPart);
306:
307: EmailPart tmp = new EmailPart();
308: File f = new File(icsFileName);
309: BufferedInputStream bis = new BufferedInputStream(
310: new FileInputStream(f));
311: byte data[] = new byte[(int) f.length() + 2];
312: bis.read(data);
313: bis.close();
314:
315: MimeBodyPart bp = new MimeBodyPart();
316: DataSource ds = new ByteArrayDataSource(data, "text/vCalendar",
317: "calendar.ics");
318: bp.setDataHandler(new DataHandler(ds));
319: bp.setDisposition("attachment; filename=calendar.ics");
320: tmp.setDisposition(bp.getDisposition());
321: bp.setFileName("calendar.ics");
322: tmp.setDataSource(ds);
323: tmp.setContent(bp.getContent());
324: parts.add(tmp);
325: tmp.setFileName("calendar.ics");
326: tmp.setContentType("text/vCalendar");
327: email.setParts(parts);
328:
329: // it is time to send the email object message
330:
331: Smtp smtp = new Smtp(connProfile, auth);
332: // we are not really a lot interested if the mail is sent or not.
333: smtp.send(email, false);
334:
335: AuthProfile authTmp = new AuthProfile();
336: authTmp.setUsername(toUsername);
337:
338: obj.setRemindedBefore("true");
339: obj.setLastDismissedAt(new Timestamp(new Date().getTime()));
340:
341: CalendarObject objW = obj.getUnwrapped();
342:
343: CalendarDBController.saveEvent(authTmp, objW);
344: }
345:
346: private static HashMap configs = new HashMap();
347:
348: public static String getText(String key) {
349: try {
350: if (lang == null)
351: lang = "en";
352: Locale loc = new Locale("en");
353: try {
354: loc = new Locale(lang);
355: } catch (Exception e) {
356: }
357:
358: String clsPath = Paths.getClsFolder();
359:
360: Configuration config = (Configuration) configs.get(lang);
361: if (config == null) {
362: config = new PropertiesConfiguration(new File(clsPath
363: + "/org/claros/intouch/i18n/lang_" + loc
364: + ".properties"));
365: configs.put(lang, config);
366: }
367: return config.getString(key);
368: } catch (ConfigurationException e) {
369: return null;
370: }
371: }
372:
373: private static String formatDate(Timestamp ts) {
374: Locale loc = new Locale(lang);
375:
376: SimpleDateFormat sdf = new SimpleDateFormat(
377: "dd MMMMM yyyy HH:mm", loc);
378: return sdf.format(new Date(ts.getTime()));
379: }
380: }
|