1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-08-13 17:03:48 -04:00

Added a code page that was missed. Built out the architecture for generic store/specialized protocol model. Implemented getPersonalNamespaces for ActiveSyncProtocol. Some logic in ActiveSyncProtocol.java should be abstracted further and has a little bit of cleanup work needed.

This commit is contained in:
Matthew Brace 2009-03-16 04:26:04 +00:00
parent f0bfb31883
commit 6949a04d28
26 changed files with 745 additions and 107 deletions

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for AirNotify in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class AirNotifyCodePage extends CodePage {
public class AirNotifyCodePage extends CodePage {
/**
* Constructor for AirNotifyCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for AirSyncBase in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class AirSyncBaseCodePage extends CodePage {
public class AirSyncBaseCodePage extends CodePage {
/**
* Constructor for AirSyncBaseCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for AirSync in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class AirSyncCodePage extends CodePage {
public class AirSyncCodePage extends CodePage {
/**
* Constructor for AirSyncCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Calendar in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class CalendarCodePage extends CodePage {
public class CalendarCodePage extends CodePage {
/**
* Constructor for CalendarCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,4 @@
package com.android.email;
package com.android.email.mail.internet;
import java.util.HashMap;

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Contacts2 in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class Contacts2CodePage extends CodePage {
public class Contacts2CodePage extends CodePage {
/**
* Constructor for Contacts2CodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Contacts in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class ContactsCodePage extends CodePage {
public class ContactsCodePage extends CodePage {
/**
* Constructor for ContactsCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for DocumentLibrary in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class DocumentLibraryCodePage extends CodePage {
public class DocumentLibraryCodePage extends CodePage {
/**
* Constructor for DocumentLibraryCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Emails in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class EmailCodePage extends CodePage {
public class EmailCodePage extends CodePage {
/**
* Constructor for EmailCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for FolderHierarchy in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class FolderHierarchyCodePage extends CodePage {
public class FolderHierarchyCodePage extends CodePage {
/**
* Constructor for FolderHierarchyCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for GAL in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class GALCodePage extends CodePage {
public class GALCodePage extends CodePage {
/**
* Constructor for GALCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for ItemEstimate in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class ItemEstimateCodePage extends CodePage {
public class ItemEstimateCodePage extends CodePage {
/**
* Constructor for ItemEstimateCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for ItemOperations in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class ItemOperationsCodePage extends CodePage {
public class ItemOperationsCodePage extends CodePage {
/**
* Constructor for ItemOperationsCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for MeetingResponse in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class MeetingResponseCodePage extends CodePage {
public class MeetingResponseCodePage extends CodePage {
/**
* Constructor for MeetingResponseCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Move in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class MoveCodePage extends CodePage {
public class MoveCodePage extends CodePage {
/**
* Constructor for MoveCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Ping in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class PingCodePage extends CodePage {
public class PingCodePage extends CodePage {
/**
* Constructor for PingCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Provision in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class ProvisionCodePage extends CodePage {
public class ProvisionCodePage extends CodePage {
/**
* Constructor for ProvisionCodePage. Initializes all of the code page values.
*/

View File

@ -0,0 +1,44 @@
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for ResolveRecipients in the ActiveSync protocol.
* The code page number is 10.
*
* @version 1.0
* @author Matthew Brace
*/
public class ResolveRecipientsCodePage extends CodePage {
/**
* Constructor for ResolveRecipientsCodePage. Initializes all of the code page values.
*/
public ResolveRecipientsCodePage() {
/* Maps String to Token for the code page */
codepageTokens.put("ResolveRecipients", 0x05);
codepageTokens.put("Response", 0x06);
codepageTokens.put("Status", 0x07);
codepageTokens.put("Type", 0x08);
codepageTokens.put("Recipient", 0x09);
codepageTokens.put("DisplayName", 0x0a);
codepageTokens.put("EmailAddress", 0x0b);
codepageTokens.put("Certificates", 0x0c);
codepageTokens.put("Certificate", 0x0d);
codepageTokens.put("MiniCertificate", 0x0e);
codepageTokens.put("Options", 0x0f);
codepageTokens.put("To", 0x10);
codepageTokens.put("CertificateRetrieval", 0x11);
codepageTokens.put("RecipientCount", 0x12);
codepageTokens.put("MaxCertificates", 0x13);
codepageTokens.put("MaxAmbiguousRecipients", 0x14);
codepageTokens.put("CertificateCount", 0x15);
/* Maps token to string for the code page */
for (String s : codepageTokens.keySet()) {
codepageStrings.put(codepageTokens.get(s), s);
}
codePageIndex = 0x0a;
codePageName = "ResolveRecipients";
}
}

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Search in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class SearchCodePage extends CodePage {
public class SearchCodePage extends CodePage {
/**
* Constructor for SearchCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Settings in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class SettingsCodePage extends CodePage {
public class SettingsCodePage extends CodePage {
/**
* Constructor for SettingsCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for Tasks in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class TasksCodePage extends CodePage {
public class TasksCodePage extends CodePage {
/**
* Constructor for TasksCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,6 @@
package com.android.email;
package com.android.email.mail.internet;
import com.android.email.mail.internet.CodePage;
/**
* This class is the specific code page for ValidateCert in the ActiveSync protocol.
@ -7,7 +9,7 @@ package com.android.email;
* @version 1.0
* @author Matthew Brace
*/
class ValidateCertCodePage extends CodePage {
public class ValidateCertCodePage extends CodePage {
/**
* Constructor for ValidateCertCodePage. Initializes all of the code page values.
*/

View File

@ -1,4 +1,4 @@
package com.android.email;
package com.android.email.mail.internet;
import java.io.BufferedOutputStream;
import java.io.BufferedInputStream;
@ -20,7 +20,7 @@ import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import com.android.email.Utility;
import com.android.email.CodePage;
import com.android.email.mail.internet.CodePage;
/**
* This class represents an entity for converting between WBXML and XML. The process uses
@ -214,11 +214,16 @@ public class WBXML {
streamByte = (streamByte ^ 128);
}
elementName = codepage.getCodePageString(streamByte);
outputBuffer = "<"+currentNamespace+":"+elementName;
outputBuffer = "<"+elementName;
if (xmlStack.empty()) {
outputBuffer = outputBuffer + " xmlns=\""+currentNamespace+"\"";
}
//outputBuffer = "<"+currentNamespace+":"+elementName;
/* If bit 6 is set, it has content */
if (content > 0) {
xmlStack.push(currentNamespace+":"+elementName);
//xmlStack.push(currentNamespace+":"+elementName);
xmlStack.push(elementName);
}
if (content > 0 && attribute == 0) {

View File

@ -4,13 +4,20 @@ import android.util.Log;
import com.android.email.Email;
import com.android.email.Utility;
import com.android.email.mail.Folder;
import com.android.email.mail.ProtocolException;
import com.android.email.mail.internet.HttpGeneric;
import com.android.email.mail.Store;
import com.android.email.mail.internet.*;
import com.android.email.mail.internet.WBXML;
import com.android.email.mail.internet.protocol.Protocol;
import com.android.email.mail.store.ActiveSyncStore;
import com.android.email.mail.transport.TrustedSocketFactory;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;
@ -19,21 +26,35 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.entity.AbstractHttpEntity;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
/**
* A class for handling all the protocol level communication and
* data for the Microsoft Exchange ActiveSync protocol.
*
* @version .1
* @version .2
* @author Matthew Brace
*/
public class ActiveSyncProtocol extends Protocol {
@ -45,9 +66,13 @@ public class ActiveSyncProtocol extends Protocol {
private String mAuthString; /* Stores the base64 encoded string used in headers for authentication */
private DefaultHttpClient mHttpClient = null; /* Stores the HttpClient to be used for requests */
private String mFolderSyncKey = "0"; /* Stores the consecutive sync key for states for folders */
CodePage[] mCodePages;
WBXML mWbxmlCoder;
private static enum supportedCommands { /* Stores the supported commands */
checkSettings;
checkSettings, getFolderHierarchy;
};
/**
@ -119,6 +144,7 @@ public class ActiveSyncProtocol extends Protocol {
* Realistically the entire object should be rebuilt if this fails, but could
* fail due to network problems, etc.
*/
@Override
public boolean checkSettings() {
boolean result = false;
try {
@ -127,9 +153,9 @@ public class ActiveSyncProtocol extends Protocol {
processRequest(mHost + "/Microsoft-Server-ActiveSync",
"OPTIONS",
null,
null,
headers,
false);
false,
"");
result = true;
} catch (ProtocolException pe) {
result = false;
@ -177,11 +203,11 @@ public class ActiveSyncProtocol extends Protocol {
*/
private DataSet processRequest(String url,
String method,
String messageBody,
String contentType,
AbstractHttpEntity messageEntity,
HashMap<String, String> headers,
boolean needsParsing) throws ProtocolException {
DataSet result = new DataSet();
boolean needsParsing,
String dataTag) throws ProtocolException {
DataSet result = new DataSet(dataTag);
DefaultHttpClient httpclient = getHttpClient();
if (url == null) {
@ -193,14 +219,11 @@ public class ActiveSyncProtocol extends Protocol {
try {
int statusCode = -1;
StringEntity messageEntity = null;
HttpGeneric httpmethod = new HttpGeneric(url);
HttpResponse response;
HttpEntity entity;
if (messageBody != null) {
messageEntity = new StringEntity(messageBody);
messageEntity.setContentType(contentType);
if (messageEntity != null) {
httpmethod.setEntity(messageEntity);
}
@ -229,7 +252,29 @@ public class ActiveSyncProtocol extends Protocol {
if (entity != null &&
needsParsing) {
/* Unsupported at this time */
try {
String responseContentType = response.getFirstHeader("Content-Type").getValue();
InputStream istream = entity.getContent();
if (responseContentType.startsWith("application/vnd.ms-sync")) {
WBXML decoder = getWbxml();
ByteArrayOutputStream wbxmlStream = new ByteArrayOutputStream();
decoder.convertWbxmlToXml(istream, wbxmlStream);
istream = new BufferedInputStream(new ByteArrayInputStream(wbxmlStream.toByteArray()), 200000);
}
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
ParseHandler myHandler = new ParseHandler(result.getContentTag());
xr.setContentHandler(myHandler);
xr.parse(new InputSource(istream));
result = myHandler.getDataSet();
} catch (SAXException se) {
Log.e(Email.LOG_TAG, "SAXException in processRequest() " + se + "\nTrace: " + processException(se));
} catch (ParserConfigurationException pce) {
Log.e(Email.LOG_TAG, "ParserConfigurationException in processRequest() " + pce + "\nTrace: " + processException(pce));
}
}
} catch (UnsupportedEncodingException uee) {
Log.e(Email.LOG_TAG,
@ -243,6 +288,35 @@ public class ActiveSyncProtocol extends Protocol {
return result;
}
private WBXML getWbxml() {
if (mWbxmlCoder == null) {
mCodePages = new CodePage[22];
mCodePages[0] = new AirSyncCodePage();
mCodePages[1] = new ContactsCodePage();
mCodePages[2] = new EmailCodePage();
mCodePages[3] = new AirNotifyCodePage();
mCodePages[4] = new CalendarCodePage();
mCodePages[5] = new MoveCodePage();
mCodePages[6] = new ItemEstimateCodePage();
mCodePages[7] = new FolderHierarchyCodePage();
mCodePages[8] = new MeetingResponseCodePage();
mCodePages[9] = new TasksCodePage();
mCodePages[0xa] = new ResolveRecipientsCodePage();
mCodePages[0xb] = new ValidateCertCodePage();
mCodePages[0xc] = new Contacts2CodePage();
mCodePages[0xd] = new PingCodePage();
mCodePages[0xe] = new ProvisionCodePage();
mCodePages[0xf] = new SearchCodePage();
mCodePages[0x10] = new GALCodePage();
mCodePages[0x11] = new AirSyncBaseCodePage();
mCodePages[0x12] = new SettingsCodePage();
mCodePages[0x13] = new DocumentLibraryCodePage();
mCodePages[0x14] = new ItemOperationsCodePage();
mWbxmlCoder = new WBXML(mCodePages);
}
return mWbxmlCoder;
}
/**
* Returns a string of the stacktrace for a Throwable to allow for easy inline printing of errors.
*/
@ -283,15 +357,186 @@ public class ActiveSyncProtocol extends Protocol {
"\n\nResponse: " + responseText;
}
@Override
public Folder[] getFolderHierarchy(Store store) {
ActiveSyncStore astore = (ActiveSyncStore) store;
String xmlData = ASXmlRequests.getFolderSyncXml(mFolderSyncKey);
ArrayList<Folder> folderList = new ArrayList<Folder>();
HashMap<String, String> headers = new HashMap<String, String>();
DataSet resultSet = new DataSet("");
ByteArrayOutputStream dataIn = new ByteArrayOutputStream();
WBXML encoder = getWbxml();
ByteArrayEntity messageEntity;
encoder.convertXmlToWbxml(new ByteArrayInputStream(xmlData.getBytes()),
dataIn);
try {
HashMap<String, String> resultData;
HashMap<String, String>[] resultSetArray;
dataIn.flush();
messageEntity = new ByteArrayEntity(dataIn.toByteArray());
messageEntity.setContentType("application/vnd.ms-sync.wbxml");
headers.put("MS-ASProtocolVersion", "2.5");
headers.put("Content-Type", "application/vnd.ms-sync.wbxml");
resultSet = processRequest(mHost + "/Microsoft-Server-ActiveSync?User="+mUsername+"&DeviceId=6F24CAD599A5BF1A690246B8C68FAE8D&DeviceType=PocketPC&Cmd=FolderSync",
"POST",
messageEntity,
headers,
true,
"Add");
resultData = resultSet.getResultData();
resultSetArray = resultSet.getResultArray();
if (resultData.containsKey("Status") &&
resultData.get("Status").equals("1")) {
for (int i = 0, count = resultSetArray.length; i < count; i++) {
ActiveSyncStore.ActiveSyncFolder folder = astore.new ActiveSyncFolder(resultSetArray[i].get("DisplayName"),
resultSetArray[i].get("ServerId"));
folderList.add(folder);
}
}
} catch (IOException ioe) {
Log.e(Email.LOG_TAG, "IOException in getFolderHierarchy: " + ioe + "\nTrace: " + processException(ioe));
} catch (ProtocolException pe) {
Log.e(Email.LOG_TAG, "ProtocolException in getFolderHierachy: " + pe + "\nTrace: " + processException(pe));
} catch (Exception e) {
Log.e(Email.LOG_TAG, "Exception in getFolderHierarchy: " + e + "\nTrace: " + processException(e));
}
return folderList.toArray(new Folder[] {});
}
/**
* Final class with private constructor so it cannot be instantiated. Holds, processes and
* creates the XML requests for ActiveSync.
*/
public static class ASXmlRequests {
/** This is never called */
private ASXmlRequests() {
}
/**
* Returns the XML string for the command FolderSync with the supplied syncKey.
*/
public static String getFolderSyncXml(String syncKey) {
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><FolderSync xmlns=\"FolderHierarchy\"><SyncKey>";
xml = xml + syncKey + "</SyncKey></FolderSync>";
return xml;
}
}
/**
* Dataset for all XML parses.
* Data is stored in a single format inside the class and is formatted appropriately
* depending on the accessor calls made.
* There are two sources of data that are stored.
* 1) An array of HashMaps of tags and characters contained between open and close tags for
* the supplied tag.
* 2) A HashMap of tags and characters contained between those tags that don't fall within
* the elements of the supplied tag.
* For entries that don't require an array of HashMaps for the result, an empty string can
* be used.
*/
public class DataSet {
public DataSet() {
String contentTag = new String();
boolean insideContentTag = false;
ArrayList<HashMap> resultSet;
HashMap<String, String> resultData;
HashMap<String, String> tempResultSet;
Stack<String> tagStack;
public DataSet(String tag) {
contentTag = tag;
resultSet = new ArrayList<HashMap>();
resultData = new HashMap<String, String>();
tempResultSet = new HashMap<String, String>();
tagStack = new Stack<String>();
}
public String getContentTag() {
return contentTag;
}
public void push(String tag) {
if (tag.equals(contentTag)) {
insideContentTag = true;
}
tagStack.push(tag);
}
public void pop() {
if (tagStack.peek().equals(contentTag)) {
resultSet.add(tempResultSet);
insideContentTag = false;
tempResultSet = new HashMap<String, String>();
}
tagStack.pop();
}
public void addCharacters(char[] ch, int start, int end) {
if (insideContentTag) {
tempResultSet.put(tagStack.peek(), new String(ch, start, end));
} else {
resultData.put(tagStack.peek(), new String(ch, start, end));
}
}
public HashMap[] getResultArray() {
HashMap<String, String>[] result = new HashMap[resultSet.size()];
result = resultSet.toArray(result);
return result;
}
public HashMap getResultData() {
return resultData;
}
}
/**
* XML Parsing Handler
* Can handle all XML handling needs
*/
public class ParseHandler extends DefaultHandler {
private DataSet mDataSet;
private String mContentTag = "";
public DataSet getDataSet() {
return this.mDataSet;
}
public ParseHandler(String contentTag) {
super();
mContentTag = contentTag;
}
@Override
public void startDocument() throws SAXException {
this.mDataSet = new DataSet(mContentTag);
}
@Override
public void endDocument() throws SAXException {
/* Do nothing */
}
@Override
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
mDataSet.push(localName);
}
@Override
public void endElement(String namespaceURI, String localName, String qName) {
mDataSet.pop();
}
@Override
public void characters(char ch[], int start, int length) {
mDataSet.addCharacters(ch, start, length);
}
}
}

View File

@ -1,13 +1,106 @@
package com.android.email.mail.internet.protocol;
import com.android.email.mail.FetchProfile;
import com.android.email.mail.Flag;
import com.android.email.mail.Folder;
import com.android.email.mail.Message;
import com.android.email.mail.MessageRetrievalListener;
import com.android.email.mail.Store;
import com.android.email.mail.Folder.FolderType;
/**
* This class represents the base object for protocols.
* The only common interface required is the ability to determine if a
* command (method) is supported.
* The model is that each "command" supported in any protocol has
* a stub function body here. Any protocols that support the command
* implement an overridden function and will return true on a call to
* isCommandSupported(command). This allows for a Store to conditionally
* implement behavior without needing specific knowledge of the underlying
* protocol.
*
* @version .1
* @author Matthew Brace
*/
public abstract class Protocol {
abstract boolean isCommandSupported(String command);
/**
* Always return true if it's not implemented elsewhere since this verifies
* that the connection can be successful.
*/
public boolean checkSettings() {
return true;
}
/**
* Return an empty array of Folder objects since it cannot be populated here.
*/
public Folder[] getFolderHierarchy(Store store) {
Folder[] folders = new Folder[0];
return folders;
}
public void openFolder(Folder folder) {
}
public void closeFolder(Folder folder, boolean expunge) {
}
public int getMessageCount(Folder folder, boolean isRead) {
return 0;
}
public boolean createFolder(Folder folder, FolderType type) {
return false;
}
/**
* Return true here since a false may result in a call to create the folder and we should
* assume that if it had something to hand to us, and the protocol doesn't support it, true is the
* best answer
*/
public boolean checkFolderExistence(Folder folder) {
return true;
}
public Message[] getMessagesByRange(Folder folder, int start, int end, MessageRetrievalListener listener) {
Message[] messages = new Message[0];
return messages;
}
public Message[] getMessagesByList(Folder folder, String[] uids, MessageRetrievalListener listener) {
Message[] messages = new Message[0];
return messages;
}
public void appendMessages(Folder folder, Message[] messages) {
return;
}
public void setMessageFlags(Folder folder, Message[] messages, Flag[] flags, boolean value) {
return;
}
public String getUidFromMessageId(Folder folder, Message message) {
return new String();
}
public Message[] expunge(Folder folder) {
return new Message[0];
}
public void fetch(Folder folder,
Message[] messages,
FetchProfile fp,
MessageRetrievalListener listener) {
return;
}
public void deleteFolder(Folder folder, boolean recurse) {
return;
}
}

View File

@ -11,11 +11,14 @@ import com.android.email.mail.MessageRetrievalListener;
import com.android.email.mail.MessagingException;
import com.android.email.mail.ProtocolException;
import com.android.email.mail.Store;
import com.android.email.mail.Folder.FolderType;
import com.android.email.mail.internet.MimeMessage;
import com.android.email.mail.internet.protocol.ActiveSyncProtocol;
public class ActiveSyncStore extends Store {
ActiveSyncProtocol protocol;
private static final Flag[] PERMANENT_FLAGS = { Flag.DELETED, Flag.SEEN, Flag.ANSWERED };
public ActiveSyncStore(String _uri) throws MessagingException {
try {
@ -27,13 +30,20 @@ public class ActiveSyncStore extends Store {
}
public Folder getFolder(String name) throws MessagingException {
Folder folder = new ActiveSyncFolder();
Folder folder = new ActiveSyncFolder(name);
return folder;
}
public Folder[] getPersonalNamespaces() throws MessagingException {
Folder[] folders = new ActiveSyncFolder[0];
Folder[] folders;
/** getFolderHierarchy is required for normal functionality, so throw an Exception if it's not supported */
if (!protocol.isCommandSupported("getFolderHierarchy")) {
throw new MessagingException("getFolderHierarchy not supported by ActiveSyncProtocol");
}
folders = protocol.getFolderHierarchy(this);
return folders;
}
@ -48,111 +58,312 @@ public class ActiveSyncStore extends Store {
}
}
/**
* Populates a folder with all of its information necessary to open the folder and
* opens the folder if it is supported.
*/
public void openFolder(ActiveSyncFolder folder) throws MessagingException {
if (protocol.isCommandSupported("openFolder")) {
protocol.openFolder(folder);
}
}
/**
* Closes a folder if the protocol supports it.
*/
public void closeFolder(ActiveSyncFolder folder, boolean expunge) {
if (protocol.isCommandSupported("closeFolder")) {
protocol.closeFolder(folder, expunge);
}
}
/**
* Retrieves the number of messages in a folder based on the supplied read status
* if supported by the protocol.
*/
public int getMessageCount(ActiveSyncFolder folder, boolean isRead) {
int messageCount = 0;
if (protocol.isCommandSupported("getMessageCount")) {
messageCount = protocol.getMessageCount(folder, isRead);
}
return messageCount;
}
/**
* Creates a folder if supported by the protocol
*/
public boolean createFolder(ActiveSyncFolder folder, FolderType type) {
boolean result = false;
if (protocol.isCommandSupported("createFolder")) {
result = protocol.createFolder(folder, type);
}
return result;
}
/**
* Checks whether the folder exists on the source the protocol supports.
*/
public boolean checkFolderExistence(ActiveSyncFolder folder) {
boolean result = false;
if (protocol.isCommandSupported("checkFolderExistenc")) {
result = protocol.checkFolderExistence(folder);
}
return result;
}
public Message[] getMessagesByRange(Folder folder, int start, int end, MessageRetrievalListener listener) {
Message[] messages = new Message[0];
if (protocol.isCommandSupported("getMessagesByRange")) {
messages = protocol.getMessagesByRange(folder, start, end, listener);
}
return messages;
}
public Message[] getMessagesByList(Folder folder, String[] uids, MessageRetrievalListener listener) {
Message[] messages = new Message[0];
if (protocol.isCommandSupported("getMessagesByList")) {
messages = protocol.getMessagesByList(folder, uids, listener);
}
return messages;
}
public void appendMessages(Folder folder, Message[] messages) {
if (protocol.isCommandSupported("appendMessages")) {
protocol.appendMessages(folder, messages);
} else {
Log.e(Email.LOG_TAG, "appendMessages not supported for ActiveSyncProtocol");
}
}
public void setMessageFlags(Folder folder, Message[] messages, Flag[] flags, boolean value) {
if (protocol.isCommandSupported("setMessageFlags")) {
protocol.setMessageFlags(folder, messages, flags, value);
} else {
Log.e(Email.LOG_TAG, "setMessageFlags not supported for ActiveSyncProtocol");
}
}
public String getUidFromMessageId(Folder folder, Message message) {
String uid = new String();
if (protocol.isCommandSupported("getUidFromMessageId")) {
uid = protocol.getUidFromMessageId(folder, message);
}
return uid;
}
public Message[] expunge(Folder folder) {
Message[] messages = new Message[0];
if (protocol.isCommandSupported("expunge")) {
messages = protocol.expunge(folder);
}
return messages;
}
public void fetch(Folder folder,
Message[] messages,
FetchProfile fp,
MessageRetrievalListener listener) throws MessagingException {
if (!protocol.isCommandSupported("fetch")) {
throw new MessagingException("fetch is not supported by ActiveSyncProtocol");
}
protocol.fetch(folder, messages, fp, listener);
}
public void deleteFolder(Folder folder, boolean recurse) {
if (protocol.isCommandSupported("deleteFolder")) {
protocol.deleteFolder(folder, recurse);
}
}
/** ActiveSyncFolder */
public class ActiveSyncFolder extends Folder {
public void open(OpenMode mode) throws MessagingException {
return;
private String mName;
private boolean mIsOpen = false;
private String mFolderUid;
private int mMessageCount = 0;
private int mUnreadMessageCount = 0;
/** Two pieces of data are needed to uniquely identify a folder for ActiveSync, folder name and folder uid.
* It can be unique identified by just the UID, but only the protocol will know about a uid, so two
* constructors are needed depending on what is instantiating the object.
*/
public ActiveSyncFolder(String name) {
mName = name;
}
public void close(boolean expunge) throws MessagingException {
public ActiveSyncFolder(String name, String uid) {
mName = name;
mFolderUid = uid;
}
/**
* Sets the folder uid. Accessor is provided for populating the data in case of a situation where it
* wasn't known at creation time.
*/
public void setUid(String uid) {
if (uid != null) {
mFolderUid = uid;
}
}
@Override
public void open(OpenMode mode) throws MessagingException {
if (mFolderUid == null &&
mIsOpen == false) {
ActiveSyncStore.this.openFolder(this);
} else {
mIsOpen = true;
}
return;
}
public boolean isOpen() {
return false;
@Override
public void close(boolean expunge) throws MessagingException {
mIsOpen = false;
ActiveSyncStore.this.closeFolder(this, expunge);
return;
}
@Override
public boolean isOpen() {
return mIsOpen;
}
@Override
public OpenMode getMode() throws MessagingException {
return OpenMode.READ_WRITE;
}
@Override
public boolean create(FolderType type) throws MessagingException {
return false;
boolean result = ActiveSyncStore.this.createFolder(this, type);
return result;
}
@Override
public boolean exists() throws MessagingException {
return false;
boolean result = ActiveSyncStore.this.checkFolderExistence(this);
return result;
}
@Override
public int getMessageCount() throws MessagingException {
return 0;
int messageCount = ActiveSyncStore.this.getMessageCount(this, true);
mMessageCount = messageCount;
return mMessageCount;
}
@Override
public int getUnreadMessageCount() throws MessagingException {
return 0;
int messageCount = ActiveSyncStore.this.getMessageCount(this, false);
mMessageCount = messageCount;
return mMessageCount;
}
@Override
public Message getMessage(String uid) throws MessagingException {
Message message = new MimeMessage();
Message message = new ActiveSyncMessage(uid);
return message;
}
@Override
public Message[] getMessages(int start, int end, MessageRetrievalListener listener)
throws MessagingException {
Message[] messages = new Message[0];
Message[] messages = ActiveSyncStore.this.getMessagesByRange(this, start, end, listener);
return messages;
}
@Override
public Message[] getMessages(MessageRetrievalListener listener)
throws MessagingException {
Message[] messages = new Message[0];
return messages;
return getMessages(null, listener);
}
@Override
public Message[] getMessages(String[] uids, MessageRetrievalListener listener)
throws MessagingException {
Message[] messages = new Message[0];
Message[] messages = ActiveSyncStore.this.getMessagesByList(this, uids, listener);
return messages;
}
@Override
public void appendMessages(Message[] messages) throws MessagingException {
ActiveSyncStore.this.appendMessages(this, messages);
return;
}
@Override
public void setFlags(Message[] messages, Flag[] flags, boolean value)
throws MessagingException {
ActiveSyncStore.this.setMessageFlags(this, messages, flags, value);
return;
}
@Override
public void setFlags(Flag[] flags, boolean value) throws MessagingException {
ActiveSyncStore.this.setMessageFlags(this, null, flags, value);
return;
}
@Override
public String getUidFromMessageId(Message message) throws MessagingException {
String uid = new String();
String uid = ActiveSyncStore.this.getUidFromMessageId(this, message);
return uid;
}
@Override
public Message[] expunge() throws MessagingException {
Message[] messages = new Message[0];
Message[] messages = ActiveSyncStore.this.expunge(this);
return messages;
}
@Override
public void fetch(Message[] messages,
FetchProfile fp,
MessageRetrievalListener listener) throws MessagingException {
ActiveSyncStore.this.fetch(this, messages, fp, listener);
return;
}
@Override
public void delete(boolean recurse) throws MessagingException {
ActiveSyncStore.this.deleteFolder(this, recurse);
return;
}
public String getName() {
String name = new String();
return name;
return mName;
}
public Flag[] getPermanentFlags() throws MessagingException {
Flag[] flags = new Flag[0];
return flags;
@Override
public Flag[] getPermanentFlags() throws MessagingException {
return PERMANENT_FLAGS;
}
}
public class ActiveSyncMessage extends MimeMessage {
public ActiveSyncMessage(String uid) {
this.mUid = uid;
}
}
}