1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.calendar.service.impl;
18
19 import java.io.*;
20 import java.text.SimpleDateFormat;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Date;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.jcr.Node;
29
30 import org.apache.commons.compress.utils.IOUtils;
31 import org.exoplatform.calendar.service.Attachment;
32 import org.exoplatform.calendar.service.Calendar;
33 import org.exoplatform.calendar.service.CalendarEvent;
34 import org.exoplatform.calendar.service.CalendarImportExport;
35 import org.exoplatform.calendar.service.CalendarService;
36 import org.exoplatform.calendar.service.EventQuery;
37 import org.exoplatform.calendar.service.ImportCalendarJob;
38 import org.exoplatform.calendar.service.ModifiedInputStream;
39 import org.exoplatform.calendar.service.Reminder;
40 import org.exoplatform.calendar.service.Utils;
41 import org.exoplatform.calendar.util.Constants;
42 import org.exoplatform.commons.utils.DateUtils;
43 import org.exoplatform.container.ExoContainerContext;
44 import org.exoplatform.services.log.ExoLogger;
45 import org.exoplatform.services.log.Log;
46 import org.exoplatform.services.scheduler.JobSchedulerService;
47 import org.exoplatform.services.scheduler.impl.JobSchedulerServiceImpl;
48
49 import org.quartz.JobDetail;
50 import org.quartz.impl.triggers.SimpleTriggerImpl;
51
52 import net.fortuna.ical4j.data.CalendarBuilder;
53 import net.fortuna.ical4j.data.CalendarOutputter;
54 import net.fortuna.ical4j.data.ParserException;
55 import net.fortuna.ical4j.model.ComponentList;
56 import net.fortuna.ical4j.model.DateTime;
57 import net.fortuna.ical4j.model.Dur;
58 import net.fortuna.ical4j.model.Parameter;
59 import net.fortuna.ical4j.model.ParameterList;
60 import net.fortuna.ical4j.model.Property;
61 import net.fortuna.ical4j.model.PropertyList;
62 import net.fortuna.ical4j.model.Recur;
63 import net.fortuna.ical4j.model.ValidationException;
64 import net.fortuna.ical4j.model.WeekDay;
65 import net.fortuna.ical4j.model.component.CalendarComponent;
66 import net.fortuna.ical4j.model.component.VAlarm;
67 import net.fortuna.ical4j.model.component.VEvent;
68 import net.fortuna.ical4j.model.component.VFreeBusy;
69 import net.fortuna.ical4j.model.component.VToDo;
70 import net.fortuna.ical4j.model.parameter.Encoding;
71 import net.fortuna.ical4j.model.parameter.Value;
72 import net.fortuna.ical4j.model.parameter.XParameter;
73 import net.fortuna.ical4j.model.property.Action;
74 import net.fortuna.ical4j.model.property.Attach;
75 import net.fortuna.ical4j.model.property.Attendee;
76 import net.fortuna.ical4j.model.property.CalScale;
77 import net.fortuna.ical4j.model.property.Categories;
78 import net.fortuna.ical4j.model.property.Clazz;
79 import net.fortuna.ical4j.model.property.Completed;
80 import net.fortuna.ical4j.model.property.Description;
81 import net.fortuna.ical4j.model.property.Due;
82 import net.fortuna.ical4j.model.property.Duration;
83 import net.fortuna.ical4j.model.property.ExDate;
84 import net.fortuna.ical4j.model.property.Location;
85 import net.fortuna.ical4j.model.property.Method;
86 import net.fortuna.ical4j.model.property.Priority;
87 import net.fortuna.ical4j.model.property.ProdId;
88 import net.fortuna.ical4j.model.property.RRule;
89 import net.fortuna.ical4j.model.property.RecurrenceId;
90 import net.fortuna.ical4j.model.property.Repeat;
91 import net.fortuna.ical4j.model.property.Status;
92 import net.fortuna.ical4j.model.property.Summary;
93 import net.fortuna.ical4j.model.property.Uid;
94 import net.fortuna.ical4j.model.property.Version;
95 import net.fortuna.ical4j.model.property.XProperty;
96 import net.fortuna.ical4j.util.CompatibilityHints;
97
98
99
100
101
102
103
104 public class ICalendarImportExport implements CalendarImportExport {
105
106 private JCRDataStorage storage_;
107
108 private static final Log logger = ExoLogger.getLogger(ICalendarImportExport.class);
109
110 public ICalendarImportExport(JCRDataStorage storage) throws Exception {
111 storage_ = storage;
112 }
113
114 public net.fortuna.ical4j.model.Calendar getCalendarComponent(net.fortuna.ical4j.model.Calendar calendar, CalendarEvent exoEvent, String componentType) throws Exception {
115 Uid id = new Uid(exoEvent.getId());
116 long start = exoEvent.getFromDateTime().getTime();
117 long end = exoEvent.getToDateTime().getTime();
118 String summary = exoEvent.getSummary();
119 CalendarComponent event = null;
120
121 if (end > 0) {
122 if (CalendarComponent.VEVENT.equals(componentType)) {
123 event = new VEvent(new DateTime(start), new DateTime(end), summary);
124 } else if (CalendarComponent.VTODO.equals(componentType)) {
125 event = new VToDo(new DateTime(start), new DateTime(end), summary);
126 }
127 } else {
128 if (CalendarComponent.VEVENT.equals(componentType)) {
129 event = new VEvent(new DateTime(start), summary);
130 } else if (CalendarComponent.VTODO.equals(componentType)) {
131 event = new VToDo(new DateTime(start), summary);
132 }
133 }
134
135 if (event == null)
136 return null;
137
138 event.getProperties().getProperty(Property.DTSTART).getParameters().add(net.fortuna.ical4j.model.parameter.Value.DATE_TIME);
139
140 event.getProperties().add(new Description(exoEvent.getDescription()));
141 event.getProperties().getProperty(Property.DESCRIPTION).getParameters().add(net.fortuna.ical4j.model.parameter.Value.TEXT);
142
143 event.getProperties().add(new Location(exoEvent.getLocation()));
144 event.getProperties().getProperty(Property.LOCATION).getParameters().add(net.fortuna.ical4j.model.parameter.Value.TEXT);
145
146 if (exoEvent.getEventCategoryName() != null) {
147 event.getProperties().add(new Categories(exoEvent.getEventCategoryName()));
148 event.getProperties().getProperty(Property.CATEGORIES).getParameters().add(net.fortuna.ical4j.model.parameter.Value.TEXT);
149 }
150 setPriorityCalEvent(event.getProperties(), exoEvent);
151
152 if (CalendarComponent.VTODO.equals(componentType)) {
153 if (exoEvent.getCompletedDateTime() != null) {
154 long completed = exoEvent.getCompletedDateTime().getTime();
155 event.getProperties().add(new Completed(new DateTime(completed)));
156 event.getProperties().getProperty(Property.COMPLETED).getParameters().add(net.fortuna.ical4j.model.parameter.Value.DATE_TIME);
157 }
158 event.getProperties().add(new Due(new DateTime(end)));
159 event.getProperties().getProperty(Property.DUE).getParameters().add(net.fortuna.ical4j.model.parameter.Value.DATE_TIME);
160 if (!Utils.isEmpty(exoEvent.getStatus())) {
161 event.getProperties().add(new Status(exoEvent.getStatus()));
162 event.getProperties().getProperty(Property.STATUS).getParameters().add(net.fortuna.ical4j.model.parameter.Value.TEXT);
163 }
164 }
165
166 if (exoEvent.getAttachment() != null && !exoEvent.getAttachment().isEmpty()) {
167 for (Attachment att : exoEvent.getAttachment()) {
168 byte bytes[] = new byte[att.getInputStream().available()];
169 att.getInputStream().read(bytes);
170 ParameterList plist = new ParameterList();
171 plist.add(new XParameter(Parameter.CN, att.getName()));
172 plist.add(new XParameter(Parameter.FMTTYPE, att.getMimeType()));
173 plist.add(Encoding.BASE64);
174 plist.add(Value.BINARY);
175 Attach attach = new Attach(plist, bytes);
176 event.getProperties().add(attach);
177 }
178 }
179
180 if (exoEvent.getReminders() != null && !exoEvent.getReminders().isEmpty()) {
181 for (Reminder r : exoEvent.getReminders()) {
182 VAlarm reminder = new VAlarm(new DateTime(r.getFromDateTime()));
183 Long times = new Long(1);
184 if (r.isRepeat())
185 times = (r.getAlarmBefore() / r.getRepeatInterval());
186 reminder.getProperties().add(new Repeat(times.intValue()));
187 reminder.getProperties().add(new Duration(new Dur(new Long(r.getAlarmBefore()).intValue())));
188 if (Reminder.TYPE_POPUP.equals(r.getReminderType())) {
189 for (String n : r.getReminderOwner().split(Utils.COMMA)) {
190 Attendee a = new Attendee(n);
191 reminder.getProperties().add(a);
192 }
193 reminder.getProperties().add(Action.DISPLAY);
194 } else {
195 for (String m : r.getEmailAddress().split(Utils.COMMA)) {
196 Attendee a = new Attendee(m);
197 reminder.getProperties().add(a);
198 }
199 reminder.getProperties().add(Action.EMAIL);
200 }
201 reminder.getProperties().add(new Summary(exoEvent.getSummary()));
202 reminder.getProperties().add(new Description(r.getDescription()));
203 reminder.getProperties().add(id);
204 calendar.getComponents().add(reminder);
205 }
206 }
207 if (exoEvent.isPrivate())
208 event.getProperties().add(new Clazz(Clazz.PRIVATE.getValue()));
209 else
210 event.getProperties().add(new Clazz(Clazz.PUBLIC.getValue()));
211 event.getProperties().getProperty(Property.CLASS).getParameters().add(net.fortuna.ical4j.model.parameter.Value.TEXT);
212 String[] attendees = exoEvent.getInvitation();
213 if (attendees != null && attendees.length > 0) {
214 for (int i = 0; i < attendees.length; i++) {
215 if (attendees[i] != null) {
216 event.getProperties().add(new Attendee(attendees[i]));
217 }
218 }
219 event.getProperties().getProperty(Property.ATTENDEE).getParameters().add(net.fortuna.ical4j.model.parameter.Value.TEXT);
220 }
221 if (!Utils.isEmpty(exoEvent.getRepeatType())) {
222 Recur rc = null;
223 if (CalendarEvent.RP_NOREPEAT.equalsIgnoreCase(exoEvent.getRepeatType())) {
224 } else if (CalendarEvent.RP_WEEKEND.equalsIgnoreCase(exoEvent.getRepeatType())) {
225 rc = new Recur(Recur.WEEKLY, 1);
226 rc.getDayList().add(WeekDay.SU);
227 rc.getDayList().add(WeekDay.SA);
228 rc.setInterval(1);
229 } else if (CalendarEvent.RP_WORKINGDAYS.equalsIgnoreCase(exoEvent.getRepeatType())) {
230 rc = new Recur(Recur.WEEKLY, 1);
231 rc.getDayList().add(WeekDay.MO);
232 rc.getDayList().add(WeekDay.TU);
233 rc.getDayList().add(WeekDay.WE);
234 rc.getDayList().add(WeekDay.TH);
235 rc.getDayList().add(WeekDay.FR);
236 rc.setInterval(1);
237 } else if (CalendarEvent.RP_WEEKLY.equalsIgnoreCase(exoEvent.getRepeatType())) {
238 rc = new Recur(Recur.WEEKLY, 1);
239 rc.getDayList().add(WeekDay.SU);
240 rc.getDayList().add(WeekDay.MO);
241 rc.getDayList().add(WeekDay.TU);
242 rc.getDayList().add(WeekDay.WE);
243 rc.getDayList().add(WeekDay.TH);
244 rc.getDayList().add(WeekDay.FR);
245 rc.getDayList().add(WeekDay.SA);
246 rc.setInterval(1);
247 } else {
248 rc = new Recur(exoEvent.getRepeatType().toUpperCase(), 1);
249 rc.setInterval(1);
250 }
251 if (rc != null) {
252 rc.setWeekStartDay(WeekDay.SU.getDay());
253 RRule r = new RRule(rc);
254 event.getProperties().add(r);
255 }
256 }
257 if (!Utils.isEmpty(exoEvent.getEventState())) {
258 XProperty xProperty = new XProperty(Utils.X_STATUS, exoEvent.getEventState());
259 event.getProperties().add(xProperty);
260 }
261 event.getProperties().add(id);
262 calendar.getComponents().add(event);
263 return calendar;
264 }
265
266 public OutputStream exportCalendar(String username, List<String> calendarIds, String type, int limited) throws Exception {
267 List<CalendarEvent> events = new ArrayList<CalendarEvent>();
268 if (type.equals(PRIVATE_TYPE)) {
269 if (limited > 0) {
270 EventQuery eventQuery = new EventQuery();
271 eventQuery.setCalendarId(calendarIds.toArray(new String[] {}));
272 eventQuery.setOrderBy(new String[] { Utils.JCR_LASTMODIFIED });
273 eventQuery.setLimitedItems(limited);
274 events = storage_.getEvents(username, eventQuery, null);
275 } else {
276 events = storage_.getUserEventByCalendar(username, calendarIds);
277 }
278 } else if (type.equals(SHARED_TYPE)) {
279 events = storage_.getSharedEventByCalendars(username, calendarIds);
280 } else if (type.equals(PUBLIC_TYPE)) {
281 events = storage_.getGroupEventByCalendar(calendarIds);
282 }
283 if (events.isEmpty())
284 return null;
285 net.fortuna.ical4j.model.Calendar calendar = new net.fortuna.ical4j.model.Calendar();
286 calendar.getProperties().add(new ProdId("-//Ben Fortuna//iCal4j 1.0//EN"));
287 calendar.getProperties().add(Version.VERSION_2_0);
288 calendar.getProperties().add(CalScale.GREGORIAN);
289 calendar.getProperties().add(Method.REQUEST);
290 for (CalendarEvent exoEvent : events) {
291 if (exoEvent.getEventType().equals(CalendarEvent.TYPE_EVENT)) {
292 calendar = getCalendarComponent(calendar, exoEvent, CalendarComponent.VEVENT);
293 } else {
294 calendar = getCalendarComponent(calendar, exoEvent, CalendarComponent.VTODO);
295 }
296 }
297 ByteArrayOutputStream bout = new ByteArrayOutputStream();
298 CalendarOutputter output = new CalendarOutputter();
299 try {
300 output.output(calendar, bout);
301 } catch (ValidationException e) {
302 if (logger.isDebugEnabled()) {
303 logger.debug("Validate error", e);
304 }
305 return null;
306 }
307 return bout;
308 }
309
310 public OutputStream exportEventCalendar(String username, String calendarId, String type, String eventId) throws Exception {
311 List<CalendarEvent> events = new ArrayList<CalendarEvent>();
312 List<String> calendarIds = Arrays.asList(new String[] { calendarId });
313
314 if (type.equals(PRIVATE_TYPE)) {
315 events = storage_.getUserEventByCalendar(username, calendarIds);
316 } else if (type.equals(SHARED_TYPE)) {
317 events = storage_.getSharedEventByCalendars(username, calendarIds);
318 } else if (type.equals(PUBLIC_TYPE)) {
319 events = storage_.getGroupEventByCalendar(calendarIds);
320 }
321 net.fortuna.ical4j.model.Calendar calendar = new net.fortuna.ical4j.model.Calendar();
322 calendar.getProperties().add(new ProdId("-//Ben Fortuna//iCal4j 1.0//EN"));
323 calendar.getProperties().add(Version.VERSION_2_0);
324 calendar.getProperties().add(CalScale.GREGORIAN);
325 calendar.getProperties().add(Method.REQUEST);
326 for (CalendarEvent exoEvent : events) {
327 if (exoEvent.getId().equals(eventId)) {
328 if (exoEvent.getEventType().equals(CalendarEvent.TYPE_EVENT)) {
329 calendar = getCalendarComponent(calendar, exoEvent, CalendarComponent.VEVENT);
330 } else {
331 calendar = getCalendarComponent(calendar, exoEvent, CalendarComponent.VTODO);
332 }
333 break;
334 }
335 }
336 ByteArrayOutputStream bout = new ByteArrayOutputStream();
337 CalendarOutputter output = new CalendarOutputter();
338 try {
339 output.output(calendar, bout);
340 } catch (ValidationException e) {
341 if (logger.isDebugEnabled()) {
342 logger.debug("Validate error", e);
343 }
344 return null;
345 }
346 return bout;
347 }
348
349
350 public List<CalendarEvent> getEventObjects(InputStream icalInputStream) throws Exception {
351 CalendarBuilder calendarBuilder = new CalendarBuilder();
352 net.fortuna.ical4j.model.Calendar iCalendar = calendarBuilder.build(icalInputStream);
353 ComponentList componentList = iCalendar.getComponents();
354 List<CalendarEvent> eventList = new ArrayList<CalendarEvent>();
355 VEvent event;
356 for (Object obj : componentList) {
357 if (obj instanceof VEvent) {
358 CalendarEvent exoEvent = new CalendarEvent();
359 event = (VEvent) obj;
360 if (event.getProperty(Property.UID) != null) {
361 exoEvent.setId(event.getProperty(Property.UID).getValue());
362 }
363 if (event.getProperty(Property.CATEGORIES) != null) {
364 exoEvent.setEventCategoryName(event.getProperty(Property.CATEGORIES).getValue().trim());
365 }
366 if (event.getSummary() != null)
367 exoEvent.setSummary(event.getSummary().getValue());
368 if (event.getDescription() != null)
369 exoEvent.setDescription(event.getDescription().getValue());
370 if (event.getStatus() != null)
371 exoEvent.setStatus(event.getStatus().getValue());
372 exoEvent.setEventType(CalendarEvent.TYPE_EVENT);
373 if (event.getStartDate() != null)
374 exoEvent.setFromDateTime(event.getStartDate().getDate());
375 if (event.getEndDate() != null)
376 exoEvent.setToDateTime(event.getEndDate().getDate());
377 if (event.getLocation() != null)
378 exoEvent.setLocation(event.getLocation().getValue());
379 logger.info(event.getPriority());
380 setPriorityExoEvent(event.getPriority(), exoEvent);
381 try {
382 RRule r = (RRule) event.getProperty(Property.RRULE);
383 if (r != null && r.getRecur() != null) {
384 Recur rc = r.getRecur();
385 rc.getFrequency();
386 if (Recur.WEEKLY.equalsIgnoreCase(rc.getFrequency())) {
387 if (rc.getDayList().size() == 2) {
388 exoEvent.setRepeatType(CalendarEvent.RP_WEEKEND);
389 } else if (rc.getDayList().size() == 5) {
390 exoEvent.setRepeatType(CalendarEvent.RP_WORKINGDAYS);
391 }
392 if (rc.getDayList().size() == 7) {
393 exoEvent.setRepeatType(CalendarEvent.RP_WEEKLY);
394 }
395 } else {
396 exoEvent.setRepeatType(rc.getFrequency().toLowerCase());
397 }
398 }
399 } catch (Exception e) {
400 if (logger.isDebugEnabled()) {
401 logger.debug("Exception in method getEventObjects", e);
402 }
403 }
404 exoEvent.setPrivate(true);
405 PropertyList attendees = event.getProperties(Property.ATTENDEE);
406 if (attendees.size() < 1) {
407 exoEvent.setInvitation(new String[] {});
408 } else {
409 String[] invitation = new String[attendees.size()];
410 for (int i = 0; i < attendees.size(); i++) {
411 invitation[i] = ((Attendee) attendees.get(i)).getValue();
412 }
413 exoEvent.setInvitation(invitation);
414 }
415 eventList.add(exoEvent);
416 }
417 }
418 return eventList;
419 }
420
421 public boolean isValidate(InputStream icalInputStream) {
422 try {
423 CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true);
424 CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING, true);
425 CalendarBuilder calendarBuilder = new CalendarBuilder();
426 calendarBuilder.build(icalInputStream);
427 return true;
428 } catch (ParserException pe) {
429 if (logger.isDebugEnabled())
430 logger.debug("Can not parsing input stream to calendar under ICal format", pe);
431 } catch (IOException ioe) {
432 if (logger.isDebugEnabled())
433 logger.debug("IO Error occurs when parsing input stream to calendar under ICal format", ioe);
434 }
435 return false;
436 }
437
438 public void importCalendar(String username,
439 InputStream icalInputStream,
440 String calendarId,
441 String calendarName,
442 java.util.Calendar from,
443 java.util.Calendar to,
444 boolean isNew) throws Exception {
445 CalendarBuilder calendarBuilder = new CalendarBuilder();
446 CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true);
447 CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING, true);
448 net.fortuna.ical4j.model.Calendar iCalendar;
449 try {
450 InputStream modStream = ModifiedInputStream.getIcsModifiedStream(icalInputStream);
451 iCalendar = calendarBuilder.build(modStream);
452 } catch (ParserException e) {
453 if (logger.isDebugEnabled()) {
454 logger.debug("ParserException occurs when building iCalendar object", e);
455 }
456 throw new ParserException("Cannot parsed the input stream to iCalendar object", e.getLineNo());
457 } catch (IOException e) {
458 if (logger.isDebugEnabled()) {
459 logger.debug("IOException occurs when building iCalendar object", e);
460 }
461 throw new IOException("IOException when parsing input stream to iCalendar object");
462 } finally {
463 icalInputStream.close();
464 }
465
466 CalendarService calService = (CalendarService) ExoContainerContext.getCurrentContainer().getComponentInstanceOfType(CalendarService.class);
467
468
469 if (isNew) {
470 Calendar exoCalendar = new Calendar();
471 exoCalendar.setName(calendarName);
472 exoCalendar.setCalendarColor(Constants.COLORS[0]);
473 exoCalendar.setDescription(iCalendar.getProductId().getValue());
474 exoCalendar.setPublic(false);
475 exoCalendar.setCalendarOwner(username);
476 calService.saveUserCalendar(username, exoCalendar, true);
477 calendarId = exoCalendar.getId();
478 }
479 CalendarEvent exoEvent;
480 ComponentList componentList = iCalendar.getComponents();
481
482 Map<String, VFreeBusy> vFreeBusyData = new HashMap<String, VFreeBusy>();
483 Map<String, VAlarm> vAlarmData = new HashMap<String, VAlarm>();
484
485 Map<String, String> originalRecurrenceEvents = new HashMap<String, String>();
486 Map<String, List<CalendarEvent>> exceptionOccurrences = new HashMap<String, List<CalendarEvent>>();
487
488 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
489 format.setTimeZone(DateUtils.getTimeZone("GMT"));
490 int calType = storage_.getTypeOfCalendar(username, calendarId);
491
492 for (Object obj : componentList) {
493 if (obj instanceof VEvent) {
494 VEvent v = (VEvent) obj;
495 if (!v.getAlarms().isEmpty()) {
496 for (Object o : v.getAlarms()) {
497 if (o instanceof VAlarm) {
498 VAlarm va = (VAlarm) o;
499 vAlarmData.put(v.getUid().getValue() + ":" + va.getProperty(Property.ACTION).getName(), va);
500 }
501 }
502 }
503 }
504 if (obj instanceof VFreeBusy)
505 vFreeBusyData.put(((VFreeBusy) obj).getUid().getValue(), (VFreeBusy) obj);
506 }
507
508 for (Object obj : componentList) {
509 if (obj instanceof VEvent) {
510 VEvent event = (VEvent) obj;
511 exoEvent = new CalendarEvent();
512 try {
513 exoEvent = RemoteCalendarServiceImpl.generateEvent(event, exoEvent, username, calendarId);
514
515 String sValue = Utils.EMPTY_STR;
516 String eValue = Utils.EMPTY_STR;
517 if (event.getStartDate() != null) {
518 if (to != null && event.getStartDate().getDate().getTime() > to.getTimeInMillis()) {
519 continue;
520 }
521 sValue = event.getStartDate().getValue();
522 exoEvent.setFromDateTime(event.getStartDate().getDate());
523 }
524 if (event.getEndDate() != null) {
525 if (from != null && event.getEndDate().getDate().getTime() < from.getTimeInMillis()) {
526 continue;
527 }
528 eValue = event.getEndDate().getValue();
529 exoEvent.setToDateTime(event.getEndDate().getDate());
530 }
531 if (sValue.length() == 8 && eValue.length() == 8) {
532 exoEvent.setToDateTime(new Date(event.getEndDate().getDate().getTime() - 1));
533 }
534 if (vFreeBusyData.get(event.getUid().getValue()) != null) {
535 exoEvent.setEventState(CalendarEvent.ST_BUSY);
536 }
537 exoEvent = RemoteCalendarServiceImpl.setEventAttachment(event, exoEvent,eValue,sValue);
538 exoEvent.setRepeatType(CalendarEvent.RP_NOREPEAT);
539 if (event.getProperty(Property.RECURRENCE_ID) != null) {
540 RecurrenceId recurId = (RecurrenceId) event.getProperty(Property.RECURRENCE_ID);
541 exoEvent.setRecurrenceId(format.format(new Date(recurId.getDate().getTime())));
542 String originalId = originalRecurrenceEvents.get(event.getUid().getValue());
543 if (originalId != null) {
544 Node originalNode = storage_.getCalendarEventNode(username, String.valueOf(calType), calendarId, originalId);
545 CalendarEvent original = storage_.getEvent(originalNode);
546 String uuid = originalNode.getUUID();
547 exoEvent.setOriginalReference(uuid);
548
549 List<String> excludeId;
550 if (original.getExcludeId() != null && original.getExcludeId().length > 0) {
551 excludeId = new ArrayList<String>(Arrays.asList(original.getExcludeId()));
552 } else {
553 excludeId = new ArrayList<String>();
554 }
555 excludeId.add(exoEvent.getRecurrenceId());
556 original.setExcludeId(excludeId.toArray(new String[0]));
557 if (calType == Calendar.TYPE_PRIVATE)
558 storage_.saveUserEvent(username, calendarId, original, false);
559 else if (calType == Calendar.TYPE_PUBLIC)
560 storage_.savePublicEvent(calendarId, original, false);
561 else if (calType == Calendar.TYPE_SHARED)
562 storage_.saveEventToSharedCalendar(username, calendarId, original, false);
563
564 } else {
565 if (exceptionOccurrences.get(event.getUid().getValue()) == null) {
566 List<CalendarEvent> exceptions = new ArrayList<CalendarEvent>();
567 exceptions.add(exoEvent);
568 exceptionOccurrences.put(event.getUid().getValue(), exceptions);
569 } else {
570 exceptionOccurrences.get(event.getUid().getValue()).add(exoEvent);
571 }
572 }
573 storage_.saveOccurrenceEvent(username, calendarId, exoEvent, true);
574 } else {
575 if (event.getProperty(Property.RRULE) != null && event.getProperty(Property.RECURRENCE_ID) == null) {
576 exoEvent = RemoteCalendarServiceImpl.calculateEvent(event, exoEvent);
577
578 originalRecurrenceEvents.put(event.getUid().getValue(), exoEvent.getId());
579
580 List<String> excludeIds = new ArrayList<String>();
581 PropertyList exdates = event.getProperties(Property.EXDATE);
582 if (exdates != null && exdates.size() > 0) {
583 for (Object exdate : exdates) {
584 for (Object date : ((ExDate) exdate).getDates()) {
585 excludeIds.add(format.format(new Date(((net.fortuna.ical4j.model.DateTime) date).getTime())));
586 }
587 }
588 }
589
590 List<CalendarEvent> exceptions = exceptionOccurrences.get(event.getUid().getValue());
591 if (exceptions != null && exceptions.size() > 0) {
592 for (CalendarEvent exception : exceptions) {
593 excludeIds.add(exception.getRecurrenceId());
594 }
595 }
596 exoEvent.setExcludeId(excludeIds.toArray(new String[0]));
597
598 if (calType == Utils.PRIVATE_TYPE)
599 storage_.saveUserEvent(username, calendarId, exoEvent, true);
600 else if (calType == Utils.SHARED_TYPE)
601 storage_.saveEventToSharedCalendar(username, calendarId, exoEvent, true);
602 else if (calType == Utils.PUBLIC_TYPE)
603 storage_.savePublicEvent(calendarId, exoEvent, true);
604
605 Node originalNode = storage_.getCalendarEventNode(username, String.valueOf(calType), calendarId, exoEvent.getId());
606 String uuid = originalNode.getUUID();
607 if (exceptions != null && exceptions.size() > 0) {
608 for (CalendarEvent exception : exceptions) {
609 exception.setOriginalReference(uuid);
610 storage_.saveOccurrenceEvent(username, calendarId, exception, false);
611 }
612 }
613 } else {
614 if (calType == Utils.PRIVATE_TYPE)
615 storage_.saveUserEvent(username, calendarId, exoEvent, true);
616 else if (calType == Utils.SHARED_TYPE)
617 storage_.saveEventToSharedCalendar(username, calendarId, exoEvent, true);
618 else if (calType == Utils.PUBLIC_TYPE)
619 storage_.savePublicEvent(calendarId, exoEvent, true);
620 }
621 }
622 } catch (Exception e) {
623 if (logger.isDebugEnabled()) {
624 logger.debug("Exception occurs when importing iCalendar component: " + event.getUid().getValue() + ". Skip this component.", e);
625 }
626 continue;
627 }
628 }
629
630 else if (obj instanceof VToDo) {
631 VToDo event = (VToDo) obj;
632 exoEvent = new CalendarEvent();
633 try {
634 exoEvent = RemoteCalendarServiceImpl.setTaskAttachment(event, exoEvent,username,calendarId,vFreeBusyData);
635 switch (storage_.getTypeOfCalendar(username, calendarId)) {
636 case Utils.PRIVATE_TYPE:
637 calService.saveUserEvent(username, calendarId, exoEvent, true);
638 break;
639 case Utils.SHARED_TYPE:
640 calService.saveEventToSharedCalendar(username, calendarId, exoEvent, true);
641 break;
642 case Utils.PUBLIC_TYPE:
643 calService.savePublicEvent(calendarId, exoEvent, true);
644 break;
645 }
646 } catch (Exception e) {
647 if (logger.isDebugEnabled()) {
648 logger.debug("Exception occurs when importing iCalendar VTODO component: " + event.getUid().getValue() + ". Skip this component.", e);
649 }
650 continue;
651 }
652 }
653 }
654
655 }
656
657 @Override
658 public ByteArrayOutputStream exportEventCalendar(CalendarEvent exoEvent) throws Exception {
659 net.fortuna.ical4j.model.Calendar calendar = new net.fortuna.ical4j.model.Calendar();
660 calendar.getProperties().add(new ProdId("-//Ben Fortuna//iCal4j 1.0//EN"));
661 calendar.getProperties().add(Version.VERSION_2_0);
662 calendar.getProperties().add(CalScale.GREGORIAN);
663 calendar.getProperties().add(Method.REQUEST);
664 if (exoEvent.getEventType().equals(CalendarEvent.TYPE_EVENT)) {
665 calendar = getCalendarComponent(calendar, exoEvent, CalendarComponent.VEVENT);
666 } else {
667 calendar = getCalendarComponent(calendar, exoEvent, CalendarComponent.VTODO);
668 }
669 ByteArrayOutputStream bout = new ByteArrayOutputStream();
670 CalendarOutputter output = new CalendarOutputter();
671 try {
672 output.output(calendar, bout);
673 } catch (ValidationException e) {
674 if (logger.isDebugEnabled()) {
675 logger.debug("Validate error", e);
676 }
677 return null;
678 }
679 return bout;
680 }
681
682 public static void setPriorityCalEvent(PropertyList propertyList, CalendarEvent exoEvent) {
683 if (exoEvent.getPriority() != null) {
684 int priority = 0;
685 for (int i = 0; i < CalendarEvent.PRIORITY.length; i++) {
686 if (exoEvent.getPriority().equalsIgnoreCase(CalendarEvent.PRIORITY[i])) {
687 if (i == CalendarEvent.PRI_MEDIUM) {
688 priority = 5;
689 } else if (i == CalendarEvent.PRI_LOW) {
690 priority = 6;
691 } else {
692 priority = i;
693 }
694 propertyList.add(new Priority(priority));
695 propertyList.getProperty(Property.PRIORITY).getParameters()
696 .add(net.fortuna.ical4j.model.parameter.Value.INTEGER);
697 break;
698 }
699 }
700 }
701 }
702
703 public static void setPriorityExoEvent(Priority priority, CalendarEvent exoEvent) {
704 if (priority != null) {
705 if (priority.getValue() != null) {
706 int priorityVl = 0;
707 try {
708 priorityVl = Integer.parseInt(priority.getValue());
709 if (1 < priorityVl && priorityVl <= 4) {
710 priorityVl = CalendarEvent.PRI_HIGH;
711 } else if (priorityVl == 5) {
712 priorityVl = CalendarEvent.PRI_MEDIUM;
713 } else if (priorityVl > 5) {
714 priorityVl = CalendarEvent.PRI_LOW;
715 }
716 exoEvent.setPriority(CalendarEvent.PRIORITY[priorityVl]);
717 } catch (NumberFormatException e) {
718 logger.warn("Can not set the priority of this event");
719 }
720 }
721 }
722 }
723
724 public void importCalendarByJob(String username,
725 InputStream icalInputStream,
726 String calendarId, String calendarName,
727 java.util.Calendar from, java.util.Calendar to,
728 boolean isNew) throws Exception {
729 JobSchedulerServiceImpl schedulerService = (JobSchedulerServiceImpl)ExoContainerContext.getCurrentContainer().
730 getComponentInstance(JobSchedulerService.class) ;
731
732 JobDetail job = findImportJob(schedulerService, calendarId);
733
734 if(job == null) {
735 byte[] icalInput = IOUtils.toByteArray(icalInputStream);
736 job = ImportCalendarJob.getImportICSFileJobDetail(username, calendarId, calendarName, icalInput, from, to, isNew);
737 }
738
739 SimpleTriggerImpl trigger = new SimpleTriggerImpl();
740 trigger.setName(calendarId);
741 trigger.setGroup(ImportCalendarJob.IMPORT_CALENDAR_JOB_GROUP_NAME);
742 trigger.setStartTime(new Date());
743
744 schedulerService.addJob(job, trigger);
745 }
746
747 public JobDetail findImportJob(JobSchedulerService schedulerService, String calendarId) throws Exception {
748 List<JobDetail> listJobs = schedulerService.getAllJobs();
749 for(JobDetail job : listJobs) {
750 if(job.getKey().getName().equals(calendarId)) {
751 return job;
752 }
753 }
754 return null;
755 }
756 }