summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/exchange/utility/CalendarUtilities.java313
-rw-r--r--src/com/android/exchange/utility/SimpleIcsWriter.java7
-rw-r--r--tests/src/com/android/exchange/utility/SimpleIcsWriterTests.java4
3 files changed, 167 insertions, 157 deletions
diff --git a/src/com/android/exchange/utility/CalendarUtilities.java b/src/com/android/exchange/utility/CalendarUtilities.java
index 09303eee5..9f16738f5 100644
--- a/src/com/android/exchange/utility/CalendarUtilities.java
+++ b/src/com/android/exchange/utility/CalendarUtilities.java
@@ -855,184 +855,191 @@ public class CalendarUtilities {
}
// Create our iCalendar writer and start generating tags
- SimpleIcsWriter ics = new SimpleIcsWriter();
- ics.writeTag("BEGIN", "VCALENDAR");
- ics.writeTag("METHOD", method);
- ics.writeTag("PRODID", "AndroidEmail");
- ics.writeTag("VERSION", "2.0");
- ics.writeTag("BEGIN", "VEVENT");
- ics.writeTag("CLASS", "PUBLIC");
- ics.writeTag("STATUS", "CONFIRMED");
- ics.writeTag("TRANSP", "OPAQUE"); // What Exchange uses
- ics.writeTag("PRIORITY", "5"); // 1 to 9, 5 = medium
- ics.writeTag("SEQUENCE", "0");
- if (uid == null) {
- uid = entityValues.getAsString(Events._SYNC_LOCAL_ID);
- }
- if (uid != null) {
- ics.writeTag("UID", uid);
- }
+ SimpleIcsWriter ics;
+ try {
+ ics = new SimpleIcsWriter();
+ ics.writeTag("BEGIN", "VCALENDAR");
+ ics.writeTag("METHOD", method);
+ ics.writeTag("PRODID", "AndroidEmail");
+ ics.writeTag("VERSION", "2.0");
+ ics.writeTag("BEGIN", "VEVENT");
+ ics.writeTag("CLASS", "PUBLIC");
+ ics.writeTag("STATUS", "CONFIRMED");
+ ics.writeTag("TRANSP", "OPAQUE"); // What Exchange uses
+ ics.writeTag("PRIORITY", "5"); // 1 to 9, 5 = medium
+ ics.writeTag("SEQUENCE", "0");
+ if (uid == null) {
+ uid = entityValues.getAsString(Events._SYNC_LOCAL_ID);
+ }
+ if (uid != null) {
+ ics.writeTag("UID", uid);
+ }
- if (entityValues.containsKey(Events.ALL_DAY)) {
- Integer ade = entityValues.getAsInteger(Events.ALL_DAY);
- ics.writeTag("X-MICROSOFT-CDO-ALLDAYEVENT", ade == 0 ? "FALSE" : "TRUE");
- }
+ if (entityValues.containsKey(Events.ALL_DAY)) {
+ Integer ade = entityValues.getAsInteger(Events.ALL_DAY);
+ ics.writeTag("X-MICROSOFT-CDO-ALLDAYEVENT", ade == 0 ? "FALSE" : "TRUE");
+ }
- long startTime = entityValues.getAsLong(Events.DTSTART);
- ics.writeTag("DTSTART", CalendarUtilities.millisToEasDateTime(startTime));
+ long startTime = entityValues.getAsLong(Events.DTSTART);
+ ics.writeTag("DTSTART", CalendarUtilities.millisToEasDateTime(startTime));
- if (!entityValues.containsKey(Events.DURATION)) {
- if (entityValues.containsKey(Events.DTEND)) {
- ics.writeTag("DTEND", CalendarUtilities.millisToEasDateTime(
- entityValues.getAsLong(Events.DTEND)));
- }
- } else {
- // Convert this into millis and add it to DTSTART for DTEND
- // We'll use 1 hour as a default
- long durationMillis = HOURS;
- Duration duration = new Duration();
- try {
- duration.parse(entityValues.getAsString(Events.DURATION));
- } catch (ParseException e) {
- // We'll use the default in this case
+ if (!entityValues.containsKey(Events.DURATION)) {
+ if (entityValues.containsKey(Events.DTEND)) {
+ ics.writeTag("DTEND", CalendarUtilities.millisToEasDateTime(
+ entityValues.getAsLong(Events.DTEND)));
+ }
+ } else {
+ // Convert this into millis and add it to DTSTART for DTEND
+ // We'll use 1 hour as a default
+ long durationMillis = HOURS;
+ Duration duration = new Duration();
+ try {
+ duration.parse(entityValues.getAsString(Events.DURATION));
+ } catch (ParseException e) {
+ // We'll use the default in this case
+ }
+ ics.writeTag("DTEND",
+ CalendarUtilities.millisToEasDateTime(startTime + durationMillis));
}
- ics.writeTag("DTEND",
- CalendarUtilities.millisToEasDateTime(startTime + durationMillis));
- }
- ics.writeTag("DTSTAMP", CalendarUtilities.millisToEasDateTime(System.currentTimeMillis()));
+ ics.writeTag("DTSTAMP",
+ CalendarUtilities.millisToEasDateTime(System.currentTimeMillis()));
- if (entityValues.containsKey(Events.EVENT_LOCATION)) {
- ics.writeTag("LOCATION", entityValues.getAsString(Events.EVENT_LOCATION));
- }
- String title = entityValues.getAsString(Events.TITLE);
- if (title != null) {
- ics.writeTag("SUMMARY", title);
- // TODO Add to strings.xml
- msg.mSubject = "Invitation" + ": " + title;
- } else {
- msg.mSubject = "Invitation";
- }
+ if (entityValues.containsKey(Events.EVENT_LOCATION)) {
+ ics.writeTag("LOCATION", entityValues.getAsString(Events.EVENT_LOCATION));
+ }
+ String title = entityValues.getAsString(Events.TITLE);
+ if (title != null) {
+ ics.writeTag("SUMMARY", title);
+ // TODO Add to strings.xml
+ msg.mSubject = "Invitation" + ": " + title;
+ } else {
+ msg.mSubject = "Invitation";
+ }
- // TODO Handle time zone
+ // TODO Handle time zone
- String desc = entityValues.getAsString(Events.DESCRIPTION);
- if (desc != null) {
- // TODO Do we need to create something (like we'll do with the email)?
- ics.writeTag("DESCRIPTION", desc);
- msg.mText = "Boilerplate" + "\n\n" + desc;
- } else {
- msg.mText = "Boilerplate";
- }
+ String desc = entityValues.getAsString(Events.DESCRIPTION);
+ if (desc != null) {
+ // TODO Do we need to create something (like we'll do with the email)?
+ ics.writeTag("DESCRIPTION", desc);
+ msg.mText = "Boilerplate" + "\n\n" + desc;
+ } else {
+ msg.mText = "Boilerplate";
+ }
- String rrule = entityValues.getAsString(Events.RRULE);
- if (rrule != null) {
- ics.writeTag("RRULE", rrule);
- }
+ String rrule = entityValues.getAsString(Events.RRULE);
+ if (rrule != null) {
+ ics.writeTag("RRULE", rrule);
+ }
- // Handle associated data EXCEPT for attendees, which have to be grouped
- ArrayList<NamedContentValues> subValues = entity.getSubValues();
- for (NamedContentValues ncv: subValues) {
- Uri ncvUri = ncv.uri;
- if (ncvUri.equals(Reminders.CONTENT_URI)) {
- // TODO Consider sending out alarm information in the meeting request, although
- // it's not obviously appropriate (i.e. telling the user what alarm to use)
- // This should be for REQUEST only
- // Here's what the VALARM would look like:
- // BEGIN:VALARM
- // ACTION:DISPLAY
- // DESCRIPTION:REMINDER
- // TRIGGER;RELATED=START:-PT15M
- // END:VALARM
+ // Handle associated data EXCEPT for attendees, which have to be grouped
+ ArrayList<NamedContentValues> subValues = entity.getSubValues();
+ for (NamedContentValues ncv: subValues) {
+ Uri ncvUri = ncv.uri;
+ if (ncvUri.equals(Reminders.CONTENT_URI)) {
+ // TODO Consider sending out alarm information in the meeting request, although
+ // it's not obviously appropriate (i.e. telling the user what alarm to use)
+ // This should be for REQUEST only
+ // Here's what the VALARM would look like:
+ // BEGIN:VALARM
+ // ACTION:DISPLAY
+ // DESCRIPTION:REMINDER
+ // TRIGGER;RELATED=START:-PT15M
+ // END:VALARM
+ }
}
- }
- // Handle attendee data here; keep track of organizer and stream it afterward
- String organizerName = null;
- String organizerEmail = null;
- ArrayList<Address> toList = new ArrayList<Address>();
- for (NamedContentValues ncv: subValues) {
- Uri ncvUri = ncv.uri;
- ContentValues ncvValues = ncv.values;
- if (ncvUri.equals(Attendees.CONTENT_URI)) {
- Integer relationship =
- ncvValues.getAsInteger(Attendees.ATTENDEE_RELATIONSHIP);
- // If there's no relationship, we can't create this for EAS
- // Similarly, we need an attendee email for each invitee
- if (relationship != null &&
- ncvValues.containsKey(Attendees.ATTENDEE_EMAIL)) {
- // Organizer isn't among attendees in EAS
- if (relationship == Attendees.RELATIONSHIP_ORGANIZER) {
- organizerName = ncvValues.getAsString(Attendees.ATTENDEE_NAME);
- organizerEmail = ncvValues.getAsString(Attendees.ATTENDEE_EMAIL);
- continue;
- }
- String attendeeEmail = ncvValues.getAsString(Attendees.ATTENDEE_EMAIL);
- String attendeeName = ncvValues.getAsString(Attendees.ATTENDEE_NAME);
- // This shouldn't be possible, but allow for it
- if (attendeeEmail == null) continue;
-
- if (messageFlag == Message.FLAG_OUTGOING_MEETING_INVITE) {
- String icalTag = ICALENDAR_ATTENDEE_INVITE;
- if (attendeeName != null) {
- icalTag += ";CN=" + attendeeName;
+ // Handle attendee data here; keep track of organizer and stream it afterward
+ String organizerName = null;
+ String organizerEmail = null;
+ ArrayList<Address> toList = new ArrayList<Address>();
+ for (NamedContentValues ncv: subValues) {
+ Uri ncvUri = ncv.uri;
+ ContentValues ncvValues = ncv.values;
+ if (ncvUri.equals(Attendees.CONTENT_URI)) {
+ Integer relationship =
+ ncvValues.getAsInteger(Attendees.ATTENDEE_RELATIONSHIP);
+ // If there's no relationship, we can't create this for EAS
+ // Similarly, we need an attendee email for each invitee
+ if (relationship != null &&
+ ncvValues.containsKey(Attendees.ATTENDEE_EMAIL)) {
+ // Organizer isn't among attendees in EAS
+ if (relationship == Attendees.RELATIONSHIP_ORGANIZER) {
+ organizerName = ncvValues.getAsString(Attendees.ATTENDEE_NAME);
+ organizerEmail = ncvValues.getAsString(Attendees.ATTENDEE_EMAIL);
+ continue;
}
- ics.writeTag(icalTag, "MAILTO:" + attendeeEmail);
- toList.add(attendeeName == null ? new Address(attendeeEmail) :
- new Address(attendeeEmail, attendeeName));
- } else if (attendeeEmail.equalsIgnoreCase(account.mEmailAddress)) {
- String icalTag = null;
- switch (messageFlag) {
- case Message.FLAG_OUTGOING_MEETING_ACCEPT:
- icalTag = ICALENDAR_ATTENDEE_ACCEPT;
- break;
- case Message.FLAG_OUTGOING_MEETING_DECLINE:
- icalTag = ICALENDAR_ATTENDEE_DECLINE;
- break;
- case Message.FLAG_OUTGOING_MEETING_TENTATIVE:
- icalTag = ICALENDAR_ATTENDEE_TENTATIVE;
- break;
- }
- if (icalTag != null) {
+ String attendeeEmail = ncvValues.getAsString(Attendees.ATTENDEE_EMAIL);
+ String attendeeName = ncvValues.getAsString(Attendees.ATTENDEE_NAME);
+ // This shouldn't be possible, but allow for it
+ if (attendeeEmail == null) continue;
+
+ if (messageFlag == Message.FLAG_OUTGOING_MEETING_INVITE) {
+ String icalTag = ICALENDAR_ATTENDEE_INVITE;
if (attendeeName != null) {
icalTag += ";CN=" + attendeeName;
}
ics.writeTag(icalTag, "MAILTO:" + attendeeEmail);
+ toList.add(attendeeName == null ? new Address(attendeeEmail) :
+ new Address(attendeeEmail, attendeeName));
+ } else if (attendeeEmail.equalsIgnoreCase(account.mEmailAddress)) {
+ String icalTag = null;
+ switch (messageFlag) {
+ case Message.FLAG_OUTGOING_MEETING_ACCEPT:
+ icalTag = ICALENDAR_ATTENDEE_ACCEPT;
+ break;
+ case Message.FLAG_OUTGOING_MEETING_DECLINE:
+ icalTag = ICALENDAR_ATTENDEE_DECLINE;
+ break;
+ case Message.FLAG_OUTGOING_MEETING_TENTATIVE:
+ icalTag = ICALENDAR_ATTENDEE_TENTATIVE;
+ break;
+ }
+ if (icalTag != null) {
+ if (attendeeName != null) {
+ icalTag += ";CN=" + attendeeName;
+ }
+ ics.writeTag(icalTag, "MAILTO:" + attendeeEmail);
+ }
}
}
}
}
- }
- // Create the organizer tag for ical
- if (organizerEmail != null) {
- String icalTag = "ORGANIZER";
- // We should be able to find this, assuming the Email is the user's email
- // TODO Find this in the account
- if (organizerName != null) {
- icalTag += ";CN=" + organizerName;
- }
- ics.writeTag(icalTag, "MAILTO:" + organizerEmail);
- if (method.equals("REPLY")) {
- toList.add(organizerName == null ? new Address(organizerEmail) :
- new Address(organizerEmail, organizerName));
+ // Create the organizer tag for ical
+ if (organizerEmail != null) {
+ String icalTag = "ORGANIZER";
+ // We should be able to find this, assuming the Email is the user's email
+ // TODO Find this in the account
+ if (organizerName != null) {
+ icalTag += ";CN=" + organizerName;
+ }
+ ics.writeTag(icalTag, "MAILTO:" + organizerEmail);
+ if (method.equals("REPLY")) {
+ toList.add(organizerName == null ? new Address(organizerEmail) :
+ new Address(organizerEmail, organizerName));
+ }
}
- }
- // If we have no "to" list, we're done
- if (toList.isEmpty()) return null;
- // Write out the "to" list
- Address[] toArray = new Address[toList.size()];
- int i = 0;
- for (Address address: toList) {
- toArray[i++] = address;
+ // If we have no "to" list, we're done
+ if (toList.isEmpty()) return null;
+ // Write out the "to" list
+ Address[] toArray = new Address[toList.size()];
+ int i = 0;
+ for (Address address: toList) {
+ toArray[i++] = address;
+ }
+ msg.mTo = Address.pack(toArray);
+
+ ics.writeTag("END", "VEVENT");
+ ics.writeTag("END", "VCALENDAR");
+ ics.flush();
+ ics.close();
+ } catch (IOException e) {;;
+ Log.w(TAG, "IOException creating message for Event");
+ return null;
}
- msg.mTo = Address.pack(toArray);
-
- ics.writeTag("END", "VEVENT");
- ics.writeTag("END", "VCALENDAR");
- ics.flush();
- ics.close();
// Create the ics attachment using the "content" field
Attachment att = new Attachment();
diff --git a/src/com/android/exchange/utility/SimpleIcsWriter.java b/src/com/android/exchange/utility/SimpleIcsWriter.java
index 2de9d25c2..fa1d26487 100644
--- a/src/com/android/exchange/utility/SimpleIcsWriter.java
+++ b/src/com/android/exchange/utility/SimpleIcsWriter.java
@@ -16,6 +16,7 @@
package com.android.exchange.utility;
import java.io.CharArrayWriter;
+import java.io.IOException;
public class SimpleIcsWriter extends CharArrayWriter {
public static final int MAX_LINE_LENGTH = 75;
@@ -34,12 +35,12 @@ public class SimpleIcsWriter extends CharArrayWriter {
}
@Override
- public void write(String str) {
+ public void write(String str) throws IOException {
int len = str.length();
// Handle the simple case here to avoid unnecessary looping
if (mLineCount + len < MAX_LINE_LENGTH) {
mLineCount += len;
- write(str);
+ super.write(str);
return;
}
for (int i = 0; i < len; i++, mLineCount++) {
@@ -53,7 +54,7 @@ public class SimpleIcsWriter extends CharArrayWriter {
}
}
- public void writeTag(String name, String value) {
+ public void writeTag(String name, String value) throws IOException {
write(name);
write(":");
write(value);
diff --git a/tests/src/com/android/exchange/utility/SimpleIcsWriterTests.java b/tests/src/com/android/exchange/utility/SimpleIcsWriterTests.java
index aed90ebb3..212627d03 100644
--- a/tests/src/com/android/exchange/utility/SimpleIcsWriterTests.java
+++ b/tests/src/com/android/exchange/utility/SimpleIcsWriterTests.java
@@ -15,6 +15,8 @@
package com.android.exchange.utility;
+import java.io.IOException;
+
import junit.framework.TestCase;
/**
@@ -35,7 +37,7 @@ public class SimpleIcsWriterTests extends TestCase {
private final String expectedSecondLineBreak =
string80Chars.charAt(SimpleIcsWriter.MAX_LINE_LENGTH - 1) + SimpleIcsWriter.LINE_BREAK;
- public void testWriter() {
+ public void testWriter() throws IOException {
// Sanity test on constant strings
assertEquals(63, string63Chars.length());
assertEquals(80, string80Chars.length());