1 15 16 package org.jical; 17 18 24 25 import java.io.BufferedReader ; 26 import java.io.File ; 27 import java.io.FileInputStream ; 28 import java.io.InputStreamReader ; 29 import java.text.SimpleDateFormat ; 30 import java.util.Date ; 31 import java.util.StringTokenizer ; 32 import java.util.TimeZone ; 33 import java.util.logging.Logger ; 34 35 public class ICalendarParser { 36 37 private String thisLine; 38 private ICalendar ical; 39 private ICalendarVEvent iCalEvent; 40 private ICalendarTimeZone icalTimeZone; 41 private boolean icalTimeZoneParser; 43 private boolean icalEventParser; 44 private String timeZoneType; 45 private TimeZone gmt; 46 47 private int lineCtr; 48 49 private Logger logger = Logger.getLogger(this.getClass().getName()); 51 52 53 54 55 public ICalendarParser() { 56 } 57 58 62 public ICalendar parse(java.lang.String iCalFilePath) { 63 File iCalFile = new File (iCalFilePath); 64 if (iCalFile.isFile()) 65 { 66 parse(iCalFile); 67 } 68 else 69 { 70 logger.fine("The input file is not a file! File provided:" + iCalFilePath); 71 ical = null; 72 } 73 return ical; 74 } 75 76 80 public ICalendar parse(File iCalFile) { 81 return parse(iCalFile,null); 82 } 83 84 public ICalendar parse(File iCalFile, String enc) { 85 gmt = TimeZone.getTimeZone("GMT"); 87 try 93 { 94 FileInputStream fin = new FileInputStream (iCalFile); 95 BufferedReader myInput = null; 96 if (enc == null) 97 myInput = new BufferedReader (new InputStreamReader (fin)); 98 else 99 myInput = new BufferedReader (new InputStreamReader (fin, enc)); 100 String buildLine = null; 101 102 104 while((thisLine = myInput.readLine()) != null) 105 { 106 114 115 lineCtr++; 116 if (thisLine.startsWith(" ") 117 || thisLine.startsWith("\u0032 ") 118 || thisLine.startsWith("\u0009") ) 119 { 120 buildLine = buildLine + thisLine.substring(1); 121 } 122 else if (buildLine != null) { 123 try { 124 processLine (buildLine); 125 } 126 catch (Exception e) { 127 logger.fine("Error processing line of ICalendar, line:" + lineCtr 128 + "iCal Line = " + buildLine 129 + "Exception" + e); 130 } 131 132 buildLine = thisLine; 133 } 134 else 135 { 136 buildLine = thisLine; 137 } 138 } 139 } 140 catch(Exception e) 141 { 142 e.printStackTrace(System.err); 143 } 144 return ical; 145 } 146 public void processLine(java.lang.String iCalLine) { 147 148 if (iCalLine.startsWith("BEGIN:VCALENDAR") ) 149 { 150 175 ical = new ICalendar(); 176 } 177 else if (iCalLine.startsWith("END:VCALENDAR") ) 178 { 179 180 } 181 else if (iCalLine.startsWith("CALSCALE") ) 182 { 183 224 225 ical.setCalScale(extractAttribute(iCalLine, "CALSCALE")); 226 } 227 228 else if (iCalLine.startsWith("PRODID") ) 229 { 230 270 ical.setProdId(extractAttribute(iCalLine, "PRODID")); 271 } 272 else if (iCalLine.startsWith("VERSION") ) 273 { 274 315 ical.setVersion(extractAttribute(iCalLine, "VERSION")); 316 } 317 else if (iCalLine.startsWith("ATTACH") ) 318 { 319 381 if (icalEventParser) 382 { 383 iCalEvent.setAttach(extractAttribute(iCalLine, "ATTACH")); 384 } 385 386 } 387 else if (iCalLine.startsWith("CATEGORIES") ) 388 { 389 437 if (icalEventParser) 438 { 439 iCalEvent.setCategories(extractAttribute(iCalLine, "CATEGORIES")); 440 } 441 } 442 else if (iCalLine.startsWith("CLASS") ) 443 { 444 488 if (icalEventParser) 489 { 490 iCalEvent.setEventClass(extractAttribute(iCalLine, "CLASS")); 491 } 492 } 493 else if (iCalLine.startsWith("COMMENT") ) 494 { 495 541 if (icalEventParser) 542 { 543 iCalEvent.setComment(extractAttribute(iCalLine, "COMMENT")); 544 } 545 } 546 else if (iCalLine.startsWith("DESCRIPTION") ) 547 { 548 606 if (icalEventParser) 607 { 608 iCalEvent.setDescription(extractAttribute(iCalLine, "DESCRIPTION")); 609 } 610 } 611 else if (iCalLine.startsWith("GEO") ) 612 { 613 694 if (icalEventParser) 695 { 696 697 String geo = extractAttribute(iCalLine, "GEO"); 699 iCalEvent.setGeo(geo); 700 StringTokenizer st = new StringTokenizer (geo,":"); 701 try 702 { 703 iCalEvent.setGeoX(new Float (st.nextToken()).floatValue()); 704 iCalEvent.setGeoY(new Float (st.nextToken()).floatValue()); 705 } 706 catch (Exception e) 707 { 708 iCalEvent.setGeoX(-1); 710 iCalEvent.setGeoY(-1); 711 logger.severe("Exception parsing int from line "+iCalLine); 712 e.printStackTrace(System.err); 713 } 714 } 715 } 716 else if (iCalLine.startsWith("LOCATION") ) 717 { 718 769 if (icalEventParser) 770 { 771 iCalEvent.setLocation(extractAttribute(iCalLine, "LOCATION")); 772 } 773 } 774 else if (iCalLine.startsWith("PERCENT-COMPLETE") ) 775 { 776 818 if (icalEventParser) 819 { 820 iCalEvent.setPercentComplete(extractAttribute(iCalLine, "PERCENT-COMPLETE")); 821 } 822 } 823 else if (iCalLine.startsWith("PRIORITY") ) 824 { 825 899 if (icalEventParser) 900 { 901 try 902 { 903 iCalEvent.setPriority(Integer.parseInt(extractAttribute(iCalLine, "PRIORITY"))); 904 } 905 catch (Exception e) 906 { 907 logger.severe("Exception parsing int from line "+iCalLine); 908 e.printStackTrace(System.err); 909 } 910 } 911 } 912 else if (iCalLine.startsWith("RESOURCES") ) 913 { 914 959 if (icalEventParser) 960 { 961 iCalEvent.setResources(extractAttribute(iCalLine, "RESOURCES")); 962 } 963 } 964 else if (iCalLine.startsWith("STATUS") ) 965 { 966 1032 if (icalEventParser) 1033 { 1034 iCalEvent.setResources(extractAttribute(iCalLine, "STATUS")); 1035 } 1036 } 1037 else if (iCalLine.startsWith("SUMMARY") ) 1038 { 1039 1084 if (icalEventParser) 1085 { 1086 iCalEvent.setSummary(extractAttribute(iCalLine, "SUMMARY")); 1087 } 1088 } 1089 else if (iCalLine.startsWith("COMPLETED") ) 1090 { 1091 1124 1125 } 1126 else if (iCalLine.startsWith("DTEND") ) 1127 { 1128 1184 if (icalEventParser == true) 1185 { 1186 iCalEvent.setDateEnd(convertIcalDate(extractAttribute(iCalLine, "DTEND"))); 1187 } 1188 } 1189 else if (iCalLine.startsWith("DUE") ) 1190 { 1191 1239 } 1240 else if (iCalLine.startsWith("DTSTART") ) 1241 { 1242 1304 1305 if (icalTimeZoneParser == true){ 1306 if (timeZoneType.equalsIgnoreCase("STANDARD") ) 1307 { 1308 icalTimeZone.setstandardDtStart(convertIcalDate(extractAttribute(iCalLine, "DTSTART"))); 1309 } 1310 else 1311 { 1312 icalTimeZone.setdaylightDtStart(convertIcalDate(extractAttribute(iCalLine, "DTSTART"))); 1313 } 1314 } 1315 else if (icalEventParser == true) 1316 { 1317 iCalEvent.setDateStart(convertIcalDate(extractAttribute(iCalLine, "DTSTART"))); 1318 } 1319 } 1320 else if (iCalLine.startsWith("DURATION") ) 1321 { 1322 1364 if (icalEventParser == true) 1365 { 1366 iCalEvent.setDuration(extractAttribute(iCalLine, "DURATION")); 1367 } 1368 } 1369 1370 else if (iCalLine.startsWith("BEGIN:VEVENT") ) 1371 { 1372 1422 icalEventParser = true; 1423 iCalEvent = new ICalendarVEvent(); 1424 iCalEvent.setEventClass(""); 1425 } 1426 else if (iCalLine.startsWith("UID:") ) 1427 { 1428 if (icalEventParser) 1429 { 1430 iCalEvent.setUid(extractAttribute(iCalLine, "UID")); 1431 } 1432 } 1433 else if (iCalLine.startsWith("END:VEVENT") ) 1434 { 1435 if (icalEventParser == true) 1436 { 1437 ical.icalEventCollection.add(iCalEvent); 1438 icalEventParser = false; 1439 } 1440 } 1441 else if (iCalLine.startsWith("BEGIN:VTODO") ) 1442 { 1443 1489 } 1490 else if (iCalLine.startsWith("END:VTODO") ) 1491 { 1492 1495 } 1496 else if (iCalLine.startsWith("BEGIN:VJOURNAL") ) 1497 { 1498 1501 } 1502 else if (iCalLine.startsWith("END:VJOURNAL") ) 1503 { 1504 1507 } 1508 else if (iCalLine.startsWith("BEGIN:VFREEBUSY") ) 1509 { 1510 1601 1602 } 1603 else if (iCalLine.startsWith("END:VFREEBUSY") ) 1604 { 1605 1608 } 1609 else if (iCalLine.startsWith("BEGIN:VTIMEZONE") ) 1610 { 1611 1961 icalTimeZone = new ICalendarTimeZone(); 1962 icalTimeZoneParser = true; 1963 } 1964 else if (iCalLine.startsWith("END:VTIMEZONE") ) 1965 { 1966 icalTimeZoneParser = false; 1967 if (icalTimeZone == null){} 1968 else { 1969 ical.icaltimeZoneCollection.add(icalTimeZone); 1970 } 1971 } 1972 else if (iCalLine.startsWith("BEGIN:VALARM") ) 1973 { 1974 2257 } 2258 else if (iCalLine.startsWith("TRANSP:") ) 2259 { 2260 2307 if (icalEventParser) 2308 { 2309 iCalEvent.setTransparency(extractAttribute(iCalLine, "TRANSP")); 2310 } 2311 } 2312 else if (iCalLine.startsWith("TZID") ) 2313 { 2314 2374 if (icalTimeZoneParser) 2375 { 2376 icalTimeZone.setTzID(extractAttribute(iCalLine, "TZID")); 2377 } 2378 } 2379 else if (iCalLine.startsWith("BEGIN:STANDARD") ) 2380 { 2381 timeZoneType = "STANDARD"; 2383 } 2384 else if (iCalLine.startsWith("BEGIN:DAYLIGHT") ) 2385 { 2386 timeZoneType = "DAYLIGHT"; 2388 } 2389 else if (iCalLine.startsWith("TZNAME") ) 2390 { 2391 2440 if (icalTimeZoneParser) 2441 { 2442 if (timeZoneType.equalsIgnoreCase("STANDARD") ) 2443 { 2444 icalTimeZone.setstandardTzName(extractAttribute(iCalLine, "TZNAME")); 2445 } 2446 else 2447 { 2448 icalTimeZone.setdaylightTzName(extractAttribute(iCalLine, "TZNAME")); 2449 } 2450 } 2451 } 2452 else if (iCalLine.startsWith("TZOFFSETFROM") ) 2453 { 2454 2494 if (icalTimeZoneParser) 2495 { 2496 String offSetVal = iCalLine.substring("TZOFFSETFROM:".length()); 2497 if (offSetVal.startsWith("+")) 2498 { 2499 offSetVal = offSetVal.substring(1); 2500 } 2501 if (timeZoneType.equalsIgnoreCase("STANDARD") ) 2502 { 2503 icalTimeZone.setstandardTzOffsetFrom(java.lang.Integer.parseInt(offSetVal)); 2504 } 2505 else 2506 { 2507 icalTimeZone.setdaylightTzOffsetFrom(java.lang.Integer.parseInt(offSetVal)); 2508 } 2509 } 2510 } 2511 else if (iCalLine.startsWith("TZOFFSETTO") ) 2512 { 2513 2550 } 2551 else if (iCalLine.startsWith("TZURL") ) 2552 { 2553 2588 } 2589 else if (iCalLine.startsWith("ATTENDEE") ) 2590 { 2591 2719 } 2721 else if (iCalLine.startsWith("CONTACT") ) 2722 { 2723 2791 if (icalEventParser) 2792 { 2793 iCalEvent.setContact(extractAttribute(iCalLine, "CONTACT")); 2796 } 2797 } 2798 else if (iCalLine.startsWith("ORGANIZER") ) 2799 { 2800 2877 if (icalEventParser) 2879 { 2880 parseOrganizer(iCalEvent, extractAttribute(iCalLine, "ORGANIZER")); 2883 } 2884 else ical.setOrganizer(extractAttribute(iCalLine, "ORGANIZER")); 2886 } 2887 else if (iCalLine.startsWith("RECURRENCE-ID") ) 2888 { 2889 2971 2972 if (icalEventParser) 2975 { 2976 iCalEvent.setRecurrenceId(true); 2977 } 2978 2979 2980 } 2981 else if (iCalLine.startsWith("RELATED-TO") ) 2982 { 2983 3051 if (icalEventParser) 3052 { 3053 iCalEvent.setRelatedTo(extractAttribute(iCalLine, "RELATED-TO")); 3054 } 3055 } 3056 else if (iCalLine.startsWith("URL") ) 3057 { 3058 3093 if (icalEventParser) 3095 { 3096 String url = extractAttribute(iCalLine, "URL"); 3097 if (url.startsWith("VALUE=URI:")) { 3098 url = url.substring(10); 3099 } 3100 iCalEvent.setUrl(url); 3101 } 3102 3103 3104 3105 } 3106 else if (iCalLine.startsWith("EXDATE") ) 3107 { 3108 3184 if (icalEventParser) 3185 { 3186 parseExDate(iCalEvent,iCalLine.substring(7)); 3188 3189 iCalEvent.setExDatesExist(true); 3191 } 3192 } 3193 else if (iCalLine.startsWith("RRULE") ) 3194 { 3195 3619 try{ 3620 if (icalTimeZoneParser) 3621 { 3622 if (timeZoneType.equalsIgnoreCase("STANDARD") ) 3623 { 3624 icalTimeZone.setstandardRRule(extractAttribute(iCalLine, "RRULE")); 3625 } 3626 else 3627 { 3628 icalTimeZone.setdaylightRRule(extractAttribute(iCalLine, "RRULE")); 3629 } 3630 } 3631 if (icalEventParser) 3632 { 3633 iCalEvent.setRRule(extractAttribute(iCalLine,"RRULE")); 3634 RepeatRules rr = new RepeatRules(); 3635 rr.parseRepeatRules(iCalEvent.getRRule()); 3636 iCalEvent.setRepeatRules(rr); 3638 } 3639 } 3640 catch (Exception e) 3641 { 3642 logger.fine("Error processing RRULE line of ICalendar, line:" + lineCtr 3643 + "Exception" + e); 3644 } 3645 } 3646 else if (iCalLine.startsWith("CREATED") ) 3647 { 3648 3685 if (icalEventParser) 3686 iCalEvent.setCreated(convertIcalDate(extractAttribute(iCalLine, "CREATED"))); 3687 } 3688 else if (iCalLine.startsWith("DTSTAMP") ) 3689 { 3690 3731 if (icalEventParser) 3732 iCalEvent.setDateStamp(convertIcalDate(extractAttribute(iCalLine, "DTSTAMP"))); 3733 } 3734 else if (iCalLine.startsWith("LAST-MODIFIED") ) 3735 { 3736 3770 if (icalEventParser) 3771 iCalEvent.setLastModified(convertIcalDate(extractAttribute(iCalLine, "LAST-MODIFIED"))); 3772 } 3773 else if (iCalLine.startsWith("SEQUENCE") ) 3774 { 3775 3856 if (icalEventParser) 3857 { 3858 try 3859 { 3860 iCalEvent.setSequence(Integer.parseInt((extractAttribute(iCalLine, "SEQUENCE")))); 3861 } 3862 catch (Exception e) 3863 { 3864 logger.severe("Parse Integer error on data :"+extractAttribute(iCalLine, "SEQUENCE") 3865 + "Exception is : "+e); 3866 e.printStackTrace(System.err); 3867 } 3868 } 3869 } 3870 else if (iCalLine.startsWith("X-") ) 3871 { 3872 3923 } 3924 else if (iCalLine.startsWith("REQUEST-STATUS") ) 3925 { 3926 4036 if (icalEventParser) 4037 { 4038 iCalEvent.setRequestStatus(extractAttribute(iCalLine, "REQUEST-STATUS")); 4039 } 4040 } 4041 else 4042 { 4043 logger.fine("Line not parsed (probably correct but check):"+iCalLine); 4044 } 4045 } 4046 4047 public Date convertIcalDate (String iCalString) 4048 { 4049 4059 4062 String iCalFormat = null; 4063 int startPoint = 0; 4064 String tzName = null; 4065 4066 TimeZone offsetZone = java.util.TimeZone.getDefault(); 4067 4068 if (iCalString.startsWith("TZID=")){ 4069 startPoint = iCalString.indexOf(":") + 1; 4071 offsetZone = getTimeZoneFromDate(iCalString, startPoint); 4073 4084 iCalString = iCalString.substring(startPoint ,startPoint + 8) + iCalString.substring(startPoint + 9, startPoint + 15); 4086 iCalFormat = "yyyyMMddHHmmss"; 4087 } 4090 else if (iCalString.startsWith("VALUE=DATE:")) 4091 { 4092 startPoint = iCalString.indexOf(":") + 1; 4093 iCalString = iCalString.substring(startPoint ,startPoint + 8); 4094 iCalFormat = "yyyyMMdd"; 4096 } 4097 else if (iCalString.startsWith("VALUE=DATE;")) 4098 { 4099 startPoint = iCalString.indexOf(";") + 1; 4101 iCalString = iCalString.substring(startPoint); 4102 startPoint = iCalString.indexOf(":") + 1; 4103 offsetZone = getTimeZoneFromDate(iCalString,startPoint); 4106 iCalString = iCalString.substring(startPoint); 4108 iCalFormat = "yyyyMMdd"; 4109 } 4110 else if (iCalString.startsWith("VALUE=DATE-TIME;")) 4111 { 4112 startPoint = iCalString.indexOf(";") + 1; 4114 iCalString = iCalString.substring(startPoint); 4115 startPoint = iCalString.indexOf(":") + 1; 4116 offsetZone = getTimeZoneFromDate(iCalString,startPoint); 4119 iCalString = iCalString.substring(startPoint); 4121 iCalFormat = "yyyyMMdd'T'HHmmss"; 4122 } 4123 else if (iCalString.startsWith("VALUE=DATE-TIME:")) 4124 { 4125 startPoint = iCalString.indexOf(":") + 1; 4127 offsetZone = gmt; 4128 iCalString = iCalString.substring(startPoint); 4129 iCalFormat = "yyyyMMdd'T'HHmmss"; 4130 } 4131 else if (iCalString.endsWith("Z")) 4132 { 4133 offsetZone = gmt; 4135 iCalString = iCalString.substring(0,8) + iCalString.substring(9,15); 4136 iCalFormat = "yyyyMMddHHmmss"; 4137 } 4138 else if (iCalString.substring(8,9).equalsIgnoreCase("T")) 4139 { 4140 iCalString = iCalString.substring(0,8) + iCalString.substring(9); 4142 iCalFormat = "yyyyMMddHHmmss"; 4143 } 4144 else 4145 { 4146 logger.fine("Date Type not known:(" + iCalString + ")"); 4147 return null; 4148 } 4149 4150 Date date = null; 4151 try 4152 { 4153 SimpleDateFormat formatter = new SimpleDateFormat (iCalFormat); 4154 formatter.setTimeZone(offsetZone); 4155 date = (Date )formatter.parse(iCalString); 4157 } 4158 catch (Exception e) 4159 { 4160 System.err.print("Parse error - " + e); 4161 } 4162 return date; 4163 } 4164 4165 public TimeZone getTimeZoneFromDate(String iCalString, int startPoint) 4166 { 4167 TimeZone tz = null; 4168 try { 4169 String tzName = null; 4170 if (iCalString.indexOf("TZID=/softwarestudio.org/Olson_20011030_5/") != -1) 4171 { 4172 tzName = iCalString.substring("TZID=/softwarestudio.org/Olson_20011030_5/".length(),startPoint -1); 4173 } 4174 else 4175 { 4176 tzName = iCalString.substring("TZID=".length(),startPoint -1); 4177 } 4178 tz = TimeZone.getTimeZone(tzName); 4179 } 4180 catch (Exception e) 4181 { 4182 System.err.print("iCal Line - " + lineCtr + "Parse error - " + e); 4183 } 4184 return tz; 4185 } 4186 public String extractAttribute(String attribLine, String attribName) 4187 { 4188 String attr = ""; 4189 4197 try { 4199 attr = attribLine.substring(attribName.length() + 1); 4200 } 4201 catch (Exception e) 4202 { 4203 logger.fine ("iCal Line - " + lineCtr + "Parse error when extracting Attribute - " 4204 + attribName + " from Attribute Line - " + attribLine 4205 + "Parse error is: " + e); 4206 } 4207 attr = attr.replaceAll("\\\\n","\n"); 4210 attr = attr.replaceAll("\\\\r","\r"); 4211 attr = attr.replaceAll("\\\\,",","); 4212 attr = attr.replaceAll("\\\\\"","\""); 4213 attr = attr.replaceAll("\\\\;",";"); 4214 4215 return attr; 4216 } 4217 4218 public void parseOrganizer(ICalendarVEvent iCalEvent, String organizer) 4219 { 4220 String iCalOrganizer = extractAttribute(organizer,"ORGANIZER"); 4221 iCalEvent.setOrganizer(iCalOrganizer); 4222 4223 int startPoint = -1; 4224 int ii = 0; 4225 boolean mailto = false; 4226 while (organizer != null && ii < 10) { 4227 ii++; 4228 String attr = null; 4229 startPoint = organizer.indexOf(":"); 4230 if (startPoint != -1) { 4231 attr = organizer.substring(0,startPoint); 4232 organizer = organizer.substring(startPoint + 1); 4233 } else { 4234 attr = organizer; 4235 organizer = null; 4236 } 4237 if (attr.toUpperCase().startsWith("CN=")) { 4238 attr = attr.substring(3); 4239 if (attr.startsWith("\"")) { 4240 attr = attr.substring(1); 4241 } 4242 if (attr.endsWith("\"")) { 4243 attr = attr.substring(0,attr.length()-1); 4244 } 4245 iCalEvent.setOrganizer(attr); 4246 } else if (attr.toUpperCase().startsWith("MAILTO")) { 4247 mailto = true; 4248 } else if (mailto) { 4249 mailto = false; 4250 iCalEvent.setOrganizerEmail(attr); 4251 } 4252 } 4253 } 4254 public void parseExDate(ICalendarVEvent iCalEvent, String exDate) 4255 { 4256 int startPoint = -1; 4257 int ii = 0; 4258 boolean mailto = false; 4259 while (exDate != null && ii < 10) { 4260 ii++; 4261 String attr = null; 4262 startPoint = exDate.indexOf(":"); 4263 if (startPoint != -1) { 4264 attr = exDate.substring(0,startPoint); 4265 exDate = exDate.substring(startPoint + 1); 4266 } else { 4267 attr = exDate; 4268 exDate = null; 4269 } 4270 if (!attr.toUpperCase().startsWith("TZID=")) { 4271 StringTokenizer st = new StringTokenizer (attr,","); 4272 while (st.hasMoreTokens()) { 4273 String exdate = st.nextToken(); 4274 logger.fine("iCalendarParser.parseExDate() add " + exdate); 4275 iCalEvent.exDateCollection.add(exdate); 4276 } 4277 } 4278 } 4279 } 4280 4281 5204 5205} 5206 | Popular Tags |