ソフトウェアエンジニア現役続行

雑多なことを綴ります

icalendar形式のファイルをgoogleカレンダーと同期する

うちの会社はグループウェアとしてサイボウズを使っています。サイボウズサーバがイントラネット上にあるため、社外からはアクセスすることができません。確かに安全ですが、社外からアクセスできないと不便なこともあります。そこで次のような方法で、サイボウズサーバに記載された自分の予定をgoogleカレンダーと同期する方法を考えました。
f:id:Oswald:20100430062954p:image
2段階の手順を踏んでいます。cronやbatで自動化すると良いです。
1. サイボウズサーバに記載された自分の予定をiCalendar形式のファイルで取得する
2. 取得したiCalendar形式のファイルをgoogleカレンダーと同期する

1. サイボウズサーバに記載された自分の予定をiCalendar形式のファイルで取得する

Cybozu2ICalというperlスクリプトを利用しました。HTTPまたはHTTPSでサイボウズサーバから取得します。--compat-google-calendarオプションを使うと、Google Calendarと互換性のあるiCalendar形式で出力されます。

2. iCalendar形式のファイルをgoogleカレンダーと同期する

GCALDaemonAPIを使って実現しました。GCALDaemonは、CALDAVというプロトコルを使ってicalendar形式のファイルをgoogleカレンダーと同期するためのJAVAアプリケーションおよびAPIです。

2-1. APIをダウンロードする

GCALDaemon ::DownloadsからAPIをダウンロードします。解凍すると、gcaldaemon-linux-1.0-beta16というディレクトリができ、gcaldaemon-linux-1.0-beta16 > GCALDaemon > libディレクトリに以下のjarファイルがあることを確認します。これらのjarファイルを使います。

  • gcal-daemon.jar
  • gdata-client.jar
  • gdata-calendar.jar
  • commons-httpclient.jar
  • commons-logging.jar
  • commons-codec.jar
  • commons-lang.jar
  • activation.jar
  • logger.jar
  • ical4j.jar
  • mail.jar
2-2. googleカレンダーと同期するプログラムを書く

GCALDaemon ::For Developersのサンプルプログラムをそのまま使いました。usernameとpasswordは自分のアカウントのものを使います。


import org.gcaldaemon.api.SyncEngine
import java.io.File;
import java.net.URL;


public class SimplestSync {


  public static void main(String[] args) {
    try {


      // This directory is used by the SyncEngine for temporary file storage
      File workDir = new File("/foo/sync");


      // Path to local iCalendar file
      File localCalendar = new File("/foo/calendar.ics");


      // Private iCal URL of a Google Calendar Use the SyncEngine.listCalendars() method to get URLs
      URL remoteCalendar = new URL("https://www.google.com/calendar/.../basic.ics");


      // Gmail user
      String username = "username@gmail.com";


      // Gmail password
      String password = "secret123";


      // Creates a synchronizer engine
      SyncEngine engine = new SyncEngine(workDir);


      // Do the synchronization
      engine.synchronize(localCalendar, remoteCalendar, username, password);


    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

2-3. コンパイルする

次のようなディレクトリ構成になっているとします。


GCALDaemon/
  │
  ├─ SimpleSync.java
  └─ lib/
     ├ gcal-daemon.jar
     ├ gdata-client.jar
     ├ gdata-calendar.jar
     ├ commons-httpclient.jar
     ├ commons-logging.jar
     ├ commons-codec.jar
     ├ commons-lang.jar
     ├ activation.jar
     ├ logger.jar
     ├ ical4j.jar
     └ mail.jar

GCALDaemonディレクトリで次のようにclasspathを指定してコンパイルします。

[Oswald@fedora GCALDeamon]$ javac -classpath .:lib/gcal-daemon.jar:lib/gdata-client.jar:lib/gdata-calendar.jar:lib/commons-httpclient.jar:lib/commons-logging.jar:lib/commons-codec.jar:lib/commons-lang.jar:lib/activation.jar:lib/logger.jar:lib/ical4j.jar:lib/mail.jar SimplestSync.java

2-4. 実行する

GCALDaemonディレクトリで次のようにclasspathを指定して実行します。


[Oswald@fedora GCALDeamon]$ java -classpath .:lib/gcal-daemon.jar:lib/gdata-client.jar:lib/gdata-calendar.jar:lib/commons-httpclient.jar:lib/commons-logging.jar:lib/commons-codec.jar:lib/commons-lang.jar:lib/activation.jar:lib/logger.jar:lib/ical4j.jar:lib/mail.jar SimplestSync

3. その他

SimpleSync.javaのremoteCalendarのURLが分からないときは、次のようにすればURLが取得できます。


import org.gcaldaemon.api.RemoteCalendar;
import org.gcaldaemon.api.SyncEngine;
import java.io.File;


public class SimplestSync {


  public static void main(String args) {
    try {


      // This directory is used by the SyncEngine for temporary file storage
      File workDir = new File("/foo/sync");


      // Gmail user
      String username = "username@gmail.com";


      // Gmail password
      String password = "secret123";


      // Creates a synchronizer engine
      SyncEngine engine = new SyncEngine(workDir);


      // Use the SyncEngine.listCalendars() method to get URLs
      RemoteCalendar calendars = engine.listCalendars(username, password);
      for (RemoteCalendar calendar : calendars){
        System.out.println(calendar.getURL());
      }


    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}