/*
* Copyright 2010 Arthur Zaczek <arthur@dasz.at>, dasz.at OG; All rights reserved.
* Copyright 2010 David Schmitt <david@dasz.at>, dasz.at OG; All rights reserved.
*
* This file is part of Kolab Sync for Android.
* Kolab Sync for Android is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
* Kolab Sync for Android is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Kolab Sync for Android.
* If not, see <http://www.gnu.org/licenses/>.
*/
package at.dasz.KolabDroid.Sync;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Date;
import javax.activation.DataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.MultipartDataSource;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import android.content.ContentValues;
import android.database.Cursor;
import android.sax.Element;
import android.util.Log;
import at.dasz.KolabDroid.Utils;
import at.dasz.KolabDroid.Provider.DatabaseHelper;
import at.dasz.KolabDroid.Provider.LocalCacheProvider;
/**
* This class creates and keeps the connections between local and remote items.
* The contained information can be used to recognize changes of items.
*/
public class CacheEntry
{
private long id;
private int localId, remoteSize;
private long remoteChangedDate;
private String localHash, remoteId, remoteImapUid;
private byte[] remoteHash;
public CacheEntry()
{
}
public CacheEntry(Cursor c)
{
setId(c.getInt(DatabaseHelper.COL_IDX_ID));
setLocalId(c.getInt(LocalCacheProvider.COL_IDX_LOCAL_ID));
setRemoteChangedDate(c
.getLong(LocalCacheProvider.COL_IDX_REMOTE_CHANGEDDATE));
setRemoteSize(c.getInt(LocalCacheProvider.COL_IDX_REMOTE_SIZE));
setLocalHash(c.getString(LocalCacheProvider.COL_IDX_LOCAL_HASH));
setRemoteId(c.getString(LocalCacheProvider.COL_IDX_REMOTE_ID));
setRemoteImapUid(c
.getString(LocalCacheProvider.COL_IDX_REMOTE_IMAP_UID));
setRemoteHash(c.getBlob(LocalCacheProvider.COL_IDX_REMOTE_HASH));
}
public void setId(long rowId)
{
this.id = rowId;
}
public long getId()
{
return id;
}
public void setLocalId(int localId)
{
this.localId = localId;
}
public int getLocalId()
{
return localId;
}
public void setRemoteChangedDate(long remoteChangedDate)
{
this.remoteChangedDate = remoteChangedDate;
}
public void setRemoteChangedDate(Date remoteChangedDate)
{
this.remoteChangedDate = remoteChangedDate.getTime();
}
public Date getRemoteChangedDate()
{
return new Date(remoteChangedDate);
}
public void setRemoteSize(int remoteSize)
{
this.remoteSize = remoteSize;
}
public int getRemoteSize()
{
return remoteSize;
}
public void setLocalHash(String localHash)
{
this.localHash = localHash;
}
public String getLocalHash()
{
return localHash;
}
public void setRemoteId(String remoteId)
{
this.remoteId = remoteId;
}
public String getRemoteId()
{
return remoteId;
}
public void setRemoteImapUid(String remoteImapUid)
{
this.remoteImapUid = remoteImapUid;
}
public String getRemoteImapUid()
{
return remoteImapUid;
}
public byte[] getRemoteHash()
{
return remoteHash;
}
public void setRemoteHash(byte[] remoteHash)
{
this.remoteHash = remoteHash;
}
/**
* Checks whether the specified CacheEntry and the Message are in sync.
* Creates a HashValue for the Remote Message, needs to retrieve it first
*
* @param entry
* @param message
* @return
* @throws MessagingException
*/
public static boolean isSameRemoteHash(CacheEntry entry, Message message)
throws MessagingException
{
Date dt = null;
if(message != null)
{
dt = Utils.getMailDate(message);
}
InputStream is = null;
try
{
DataSource mainDataSource = message.getDataHandler()
.getDataSource();
if ((mainDataSource instanceof MultipartDataSource))
{
MultipartDataSource multipart = (MultipartDataSource) mainDataSource;
for (int idx = 0; idx < multipart.getCount(); idx++)
{
BodyPart p = multipart.getBodyPart(idx);
if (!p.isMimeType("text/plain"))
{
is = p.getInputStream();
break;
}
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
boolean remoteHashIsSame = false;
if(is != null)
{
Document doc = null;
try
{
doc = Utils.getDocument(is);
String docText = Utils.getXml(doc.getDocumentElement());
byte[] remoteHash = Utils.sha1Hash(docText);
if(Arrays.equals(remoteHash, entry.getRemoteHash()))
{
remoteHashIsSame = true;
}
else
{
remoteHashIsSame = false;
}
}
catch (Exception ex)
{
Log.e("EE", ex.toString());
}
}
boolean result = entry != null && message != null
&& entry.getRemoteChangedDate().equals(dt)
&& entry.getRemoteId().equals(message.getSubject())
&& remoteHashIsSame;
if (!result)
{
if (entry == null) Log.d("syncisSame", "entry == null");
if (message == null) Log.d("syncisSame", "message == null");
if (entry != null && message != null)
{
if (!entry.getRemoteChangedDate().equals(dt))
{
Log.d("syncisSame", "getRemoteChangedDate="
+ entry.getRemoteChangedDate() + ", getReceived/SentDate="
+ dt);
}
if (!entry.getRemoteId().equals(message.getSubject()))
{
Log.d("syncisSame", "getRemoteId=" + entry.getRemoteId()
+ ", getSubject=" + message.getSubject());
}
}
}
return result;
}
/**
* Checks whether the specified CacheEntry and the Message are in sync.
*
* @param entry
* @param message
* @return
* @throws MessagingException
*/
public static boolean isSame(CacheEntry entry, Message message)
throws MessagingException
{
Date dt = null;
if(message != null)
{
dt = Utils.getMailDate(message);
}
boolean result = entry != null && message != null
&& entry.getRemoteChangedDate().equals(dt)
&& entry.getRemoteId().equals(message.getSubject());
if (!result)
{
if (entry == null) Log.d("syncisSame", "entry == null");
if (message == null) Log.d("syncisSame", "message == null");
if (entry != null && message != null)
{
if (!entry.getRemoteChangedDate().equals(dt))
{
Log.d("syncisSame", "getRemoteChangedDate="
+ entry.getRemoteChangedDate() + ", getReceived/SentDate="
+ dt);
}
if (!entry.getRemoteId().equals(message.getSubject()))
{
Log.d("syncisSame", "getRemoteId=" + entry.getRemoteId()
+ ", getSubject=" + message.getSubject());
}
}
}
return result;
}
public ContentValues toContentValues()
{
ContentValues result = new ContentValues();
if (getId() != 0)
{
result.put(DatabaseHelper.COL_ID, getId());
}
result.put(LocalCacheProvider.COL_LOCAL_ID, getLocalId());
result.put(LocalCacheProvider.COL_REMOTE_CHANGEDDATE,
getRemoteChangedDate().getTime());
result.put(LocalCacheProvider.COL_REMOTE_SIZE, getRemoteSize());
result.put(LocalCacheProvider.COL_LOCAL_HASH, getLocalHash());
result.put(LocalCacheProvider.COL_REMOTE_ID, getRemoteId());
result.put(LocalCacheProvider.COL_REMOTE_IMAP_UID, getRemoteImapUid());
result.put(LocalCacheProvider.COL_REMOTE_HASH, getRemoteHash());
return result;
}
}