JavaXT
|
|
Folder Classpackage javaxt.exchange; //****************************************************************************** //** Folder Class //****************************************************************************** /** * Used to represent a folder (e.g. "Inbox", "Contacts", etc.) * ******************************************************************************/ public class Folder { private String id; private String parentID; private String name; private String changeKey; private Integer totalCount; private Integer unreadCount; private Integer folderCount; private Connection conn; //************************************************************************** //** Constructor //************************************************************************** /** This constructor is provided for application developers who wish to * extend this class. */ protected Folder(){} //************************************************************************** //** Constructor //************************************************************************** /** Creates a new instance of this class using a folder */ protected Folder(Folder folder){ this.id = folder.id; this.parentID = folder.parentID; this.name = folder.name; this.changeKey = folder.changeKey; this.totalCount = folder.totalCount; this.unreadCount = folder.unreadCount; this.folderCount = folder.folderCount; this.conn = folder.conn; } //************************************************************************** //** Constructor //************************************************************************** /** Creates a new instance of this class using a folder name/id. * @param folderName Name of the exchange folder (e.g. inbox, contacts, etc). */ public Folder(String folderName, Connection conn) throws ExchangeException { this.conn = conn; String folderID = getDistinguishedFolderId(folderName); if (folderID==null){ folderID = "<t:FolderId Id=\"" + folderName + "\"/>"; } else{ folderID = "<t:DistinguishedFolderId Id=\"" + folderID + "\"/>"; } String msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<soap:Body>" + "<GetFolder xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<FolderShape>" + "<t:BaseShape>Default</t:BaseShape>" + "<t:AdditionalProperties>" //The following returns the LastModifiedTime for the folder. Unfortunately, //this does not reflect changes made to items in this folder. //+ "<t:ExtendedFieldURI PropertyTag=\"0x3008\" PropertyType=\"SystemTime\" />" + "<t:FieldURI FieldURI=\"folder:ParentFolderId\" />" + "</t:AdditionalProperties>" + "</FolderShape>" + "<FolderIds>" + folderID + "</FolderIds></GetFolder>" + "</soap:Body>" + "</soap:Envelope>"; parseXML(conn.execute(msg)); } //************************************************************************** //** Constructor //************************************************************************** /** Private constructor used by the getFolders() method. */ private Folder(org.w3c.dom.Node folder, Connection conn) throws ExchangeException { this.conn = conn; parseFolderNode(folder); } //************************************************************************** //** getFolders //************************************************************************** /** Returns an array of folders found in this folder. Returns a zero length * array of no folders are found. */ public Folder[] getFolders() throws ExchangeException { return getFolders("Shallow"); } //************************************************************************** //** getFolders //************************************************************************** /** Returns an array of folders found in this folder. Returns a zero length * array of no folders are found. * @param Traversal Possible values include "Deep", "Shallow", "SoftDeleted". * Defaults to "Shallow" if a null or invalid string is used. */ public Folder[] getFolders(String Traversal) throws ExchangeException { java.util.ArrayList<Folder> folders = new java.util.ArrayList<Folder>(); if (Traversal==null) Traversal = ""; if (Traversal.equalsIgnoreCase("Deep")) Traversal = "Deep"; else if (Traversal.equalsIgnoreCase("SoftDeleted")) Traversal = "SoftDeleted"; else Traversal = "Shallow"; String msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<soap:Body>" + "<FindFolder Traversal=\"" + Traversal + "\" xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<FolderShape>" + "<t:BaseShape>Default</t:BaseShape>" + "<t:AdditionalProperties>" + "<t:FieldURI FieldURI=\"folder:ParentFolderId\" />" + "</t:AdditionalProperties>" + "</FolderShape>" + "<ParentFolderIds><t:FolderId Id=\"" + id + "\"/></ParentFolderIds>" + "</FindFolder>" + "</soap:Body>" + "</soap:Envelope>"; org.w3c.dom.Document response = conn.execute(msg); for (org.w3c.dom.Node node : javaxt.xml.DOM.getElementsByTagName("Folder", response)){ folders.add(new Folder(node, conn)); } return folders.toArray(new Folder[folders.size()]); } //************************************************************************** //** createFolder //************************************************************************** /** Used to create a folder within this folder. */ public Folder createFolder(String name) throws ExchangeException { name = name.trim(); String msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<soap:Body>" + "<CreateFolder xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<ParentFolderId><t:FolderId Id=\"" + id + "\"/></ParentFolderId>" + "<Folders><t:Folder><t:DisplayName>" + name + "</t:DisplayName></t:Folder></Folders>" + "</CreateFolder>" + "</soap:Body>" + "</soap:Envelope>"; org.w3c.dom.Document response = conn.execute(msg); org.w3c.dom.Node[] nodes = javaxt.xml.DOM.getElementsByTagName("Folder", response); if (nodes.length>0){ Folder folder = new Folder(nodes[0], conn); folder.name = name; folder.totalCount = 0; folder.unreadCount = 0; folder.folderCount = 0; folder.parentID = id; return folder; } else throw new ExchangeException("Failed to create folder."); } //************************************************************************** //** rename //************************************************************************** /** Used to rename this folder. */ public void rename(String name) throws ExchangeException { changeKey = getChangeKey(conn); name = name.trim(); String msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<soap:Body>" + "<UpdateFolder xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<FolderChanges>" + "<t:FolderChange>" + "<t:FolderId Id=\"" + id + "\" ChangeKey=\"" + changeKey + "\"/>" + "<t:Updates>" + "<t:SetFolderField>" + "<t:FieldURI FieldURI=\"folder:DisplayName\" />" + "<t:Folder><t:DisplayName>" + name + "</t:DisplayName></t:Folder>" + "</t:SetFolderField>" + "</t:Updates>" + "</t:FolderChange>" + "</FolderChanges>" + "</UpdateFolder>" + "</soap:Body>" + "</soap:Envelope>"; conn.execute(msg); this.name = name; } //************************************************************************** //** move //************************************************************************** /** Used to move this folder to another folder. */ public void move(Folder destination) throws ExchangeException { String msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<soap:Body>" + "<MoveFolder xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<ToFolderId><t:FolderId Id=\"" + destination.id + "\"/></ToFolderId>" + "<FolderIds><t:FolderId Id=\"" + id + "\"/></FolderIds>" + "</MoveFolder>" + "</soap:Body>" + "</soap:Envelope>"; conn.execute(msg); } //************************************************************************** //** delete //************************************************************************** /** Used to delete this folder. */ public void delete() throws ExchangeException { String msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<soap:Body>" + "<DeleteFolder DeleteType=\"HardDelete\" xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">" + "<FolderIds><t:FolderId Id=\"" + id + "\"/></FolderIds>" + "</DeleteFolder>" + "</soap:Body>" + "</soap:Envelope>"; conn.execute(msg); } //************************************************************************** //** getChangeKey //************************************************************************** /** Used to retrieve the latest ChangeKey for this folder. This method is * required to update an item. */ protected String getChangeKey(Connection conn) throws ExchangeException { changeKey = new Folder(id, conn).changeKey; return changeKey; } private void parseXML(org.w3c.dom.Document xml) throws ExchangeException { org.w3c.dom.Node[] nodes = javaxt.xml.DOM.getElementsByTagName("FolderId", xml); if (nodes.length>0) parseFolderNode(nodes[0].getParentNode()); else throw new ExchangeException("Failed to parse FolderId."); } private void parseFolderNode(org.w3c.dom.Node folder) throws ExchangeException { org.w3c.dom.NodeList properties = folder.getChildNodes(); for (int i=0; i<properties.getLength(); i++){ org.w3c.dom.Node property = properties.item(i); if (property.getNodeType()==1){ String key = property.getNodeName(); String value = property.getTextContent().trim(); if (key.contains(":")) key = key.substring(key.indexOf(":")+1); if (key.equalsIgnoreCase("FolderId")){ id = javaxt.xml.DOM.getAttributeValue(property, "Id"); changeKey = javaxt.xml.DOM.getAttributeValue(property, "ChangeKey"); } else if(key.equalsIgnoreCase("ParentFolderId")){ parentID = javaxt.xml.DOM.getAttributeValue(property, "Id"); //javaxt.xml.DOM.getAttributeValue(property, "ChangeKey"); } else if(key.equalsIgnoreCase("DisplayName")) name = value; else if(key.equalsIgnoreCase("TotalCount")) totalCount = cint(value); else if(key.equalsIgnoreCase("ChildFolderCount")) folderCount = cint(value); else if(key.equalsIgnoreCase("UnreadCount")) unreadCount = cint(value); } } if (id==null || id.length()==0) throw new ExchangeException("Failed to parse Folder."); } private Integer cint(String str){ try{ return Integer.parseInt(str); } catch(Exception e){ return null; } } //************************************************************************** //** getID //************************************************************************** /** Returns the unique Exchange ID for this folder. */ public String getID(){ return id; } //************************************************************************** //** getParentID //************************************************************************** /** Returns the unique ID for the parent folder. */ public String getParentID(){ return parentID; } /* public String getChangeKey(){ return changeKey; } */ //************************************************************************** //** getName //************************************************************************** /** Returns the name of the folder. */ public String getName(){ return name; } //************************************************************************** //** getTotalCount //************************************************************************** /** Returns the total number of items found in this folder. */ public Integer getTotalCount(){ return totalCount; } //************************************************************************** //** getUnreadCount //************************************************************************** /** Returns the total number of unread items found in this folder. */ public Integer getUnreadCount(){ return unreadCount; } //************************************************************************** //** getChildFolderCount //************************************************************************** /** Returns the total number of folders found in this this folder. */ public Integer getChildFolderCount(){ return folderCount; } //************************************************************************** //** toString //************************************************************************** /** Returns the name of the folder. */ public String toString(){ return name; } //************************************************************************** //** getItems //************************************************************************** /** Returns an XML document with shallow representations of items found in * this folder. * @param offset Item offset. 0 implies no offset. * @param limit Maximum number of items to return. */ protected org.w3c.dom.Document getItems(int offset, int limit, java.util.HashSet<FieldURI> additionalProperties, String where, FieldOrder[] sortOrder) throws ExchangeException { if (offset<1) offset = 0; if (limit<1) limit = 1; return getItems("<m:IndexedPageItemView MaxEntriesReturned=\"" + limit + "\" Offset=\"" + offset + "\" BasePoint=\"Beginning\"/>", additionalProperties, where, sortOrder); } //************************************************************************** //** getItems //************************************************************************** /** Returns an XML document with shallow representations of items found in * this folder. * * @param view XML node representing a page view (e.g. IndexedPageItemView, * FractionalPageItemView, CalendarView, ContactsView). * * @param additionalProperties By default, this method returns a shallow * representation of each item found in this folder. You can retrieve * additional attributes by providing a list of properties * (e.g. "calendar:TimeZone", "item:Sensitivity", etc). * * @param sortOrder SQL-style order by clause used to sort the results * (e.g. "item:DateTimeReceived DESC"). */ protected org.w3c.dom.Document getItems(String view, java.util.HashSet<FieldURI> additionalProperties, String where, FieldOrder[] sortOrder) throws ExchangeException { //Parse order by statement String sort = ""; if (sortOrder!=null){ for (FieldOrder field : sortOrder){ sort += field.toXML(); } if (sort.length()>0){ sort = "<m:SortOrder>" + sort + "</m:SortOrder>"; } } //Parse where clasue and create restriction if (where==null) where = ""; else where = where.trim(); String restriction = where; //Update the view xml node. Make sure the node name is prefixed with a "m:" namespace if (view==null) view = ""; else{ view = view.trim(); String nodeName = view.substring(1, view.indexOf(">")); if (nodeName.endsWith("/")) nodeName = nodeName.substring(0, nodeName.length()-1); if (nodeName.contains(" ")) nodeName = nodeName.substring(0, nodeName.indexOf(" ")); nodeName = nodeName.trim(); if (nodeName.contains(":")){ String ns = nodeName.substring(0, nodeName.indexOf(":")); if (!ns.equals("m")){ String newNodeName = nodeName.substring(ns.length()+1); view = view.replace("<" + nodeName, "<m:" + newNodeName); view = view.replace("</" + nodeName, "</m:" + newNodeName); } } else{ view = view.replace("<" + nodeName, "<m:" + nodeName); view = view.replace("</" + nodeName, "</m:" + nodeName); } } //Pa StringBuffer props = new StringBuffer(); if (additionalProperties!=null){ java.util.Iterator<FieldURI> it = additionalProperties.iterator(); while (it.hasNext()){ FieldURI prop = it.next(); if (prop!=null){ props.append(prop.toXML("t")); //("<t:FieldURI FieldURI=\"" + prop + "\"/>"); } } } String msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\" xmlns:m=\"http://schemas.microsoft.com/exchange/services/2006/messages\">" + "<soap:Body>" + "<m:FindItem Traversal=\"Shallow\">" /* + "<m:ItemShape><t:BaseShape>Default</t:BaseShape>" //<--"Default" vs "AllProperties" + "<t:AdditionalProperties><t:FieldURI FieldURI=\"item:ItemClass\"/></t:AdditionalProperties>" + "</m:ItemShape>" */ + "<m:ItemShape>" + "<t:BaseShape>Default</t:BaseShape>" //<--"Default" vs "AllProperties" + "<t:AdditionalProperties>" + "<t:FieldURI FieldURI=\"item:ItemClass\"/>" //+ "<t:FieldURI FieldURI=\"item:LastModifiedTime\"/>" //value="item:LastModifiedTime" //<--This doesn't work... + "<t:ExtendedFieldURI PropertyTag=\"0x3008\" PropertyType=\"SystemTime\" />" //<--This returns the LastModifiedTime! + props.toString() + "</t:AdditionalProperties>" + "</m:ItemShape>" + view + restriction + sort + "<m:ParentFolderIds>" + "<t:FolderId Id=\"" + id + "\"/>" + "</m:ParentFolderIds>" + "</m:FindItem>" + "</soap:Body>" + "</soap:Envelope>"; return conn.execute(msg); } //************************************************************************** //** getIndex //************************************************************************** /** Returns a hashmap of all the items found in this folder. The hashmap key * is the item id and the corresponding value is the last modification date. */ public java.util.HashMap<String, javaxt.utils.Date> getIndex() throws ExchangeException { String msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\" xmlns:m=\"http://schemas.microsoft.com/exchange/services/2006/messages\">" + "<soap:Body>" + "<m:FindItem Traversal=\"Shallow\">" + "<m:ItemShape>" + "<t:BaseShape>IdOnly</t:BaseShape>" //<--"Default" vs "AllProperties" + "<t:AdditionalProperties>" + "<t:ExtendedFieldURI PropertyTag=\"0x3008\" PropertyType=\"SystemTime\" />" //<--This returns the LastModifiedTime! + "</t:AdditionalProperties>" + "</m:ItemShape>" + "<m:SortOrder>" + "<t:FieldOrder Order=\"Descending\">" + "<t:ExtendedFieldURI PropertyTag=\"0x3008\" PropertyType=\"SystemTime\" />" + "</t:FieldOrder>" + "</m:SortOrder>" //+ "<m:IndexedPageItemView MaxEntriesReturned=\"1\" Offset=\"0\" BasePoint=\"Beginning\"/>" + "<m:ParentFolderIds>" + "<t:FolderId Id=\"" + id + "\"/>" + "</m:ParentFolderIds>" + "</m:FindItem>" + "</soap:Body>" + "</soap:Envelope>"; org.w3c.dom.Document xml = conn.execute(msg); //new javaxt.io.File("/temp/exchange-sort.xml").write(xml); java.util.HashMap<String, javaxt.utils.Date> index = new java.util.HashMap<String, javaxt.utils.Date>(); org.w3c.dom.Node[] items = javaxt.xml.DOM.getElementsByTagName("Items", xml); if (items.length>0){ org.w3c.dom.NodeList nodes = items[0].getChildNodes(); for (int i=0; i<nodes.getLength(); i++){ org.w3c.dom.Node node = nodes.item(i); if (node.getNodeType()==1){ FolderItem item = new FolderItem(node); index.put(item.getID(), item.getLastModifiedTime()); } } } return index; } protected void findItem(){ /* <m:FindItem Traversal="Shallow" xmlns:m=".../messages" xmlns:t=".../types"> <m:ItemShape> <t:BaseShape>IdOnly</t:BaseShape> <t:AdditionalProperties> <t:FieldURI FieldURI="item:Subject" /> <t:FieldURI FieldURI="calendar:CalendarItemType" /> </t:AdditionalProperties> </m:ItemShape> <m:Restriction> <t:And> <t:IsGreaterThan> <t:FieldURI FieldURI="calendar:Start" /> <t:FieldURIOrConstant> <t:Constant Value="2006-10-16T00:00:00-08:00" /> </t:FieldURIOrConstant> </t:IsGreaterThan> <t:IsLessThan> <t:FieldURI FieldURI="calendar:End" /> <t:FieldURIOrConstant> <t:Constant Value="2006-10-20T23:59:59-08:00" /> </t:FieldURIOrConstant> </t:IsLessThan> </t:And> </m:Restriction> <m:ParentFolderIds> <t:DistinguishedFolderId Id="calendar"/> </m:ParentFolderIds> </m:FindItem> */ } //************************************************************************** //** getDistinguishedFolderIds //************************************************************************** /** Returns a list of Distinguished Folder IDs. */ public static String[] getDistinguishedFolderIds(){ return DistinguishedFolderIds; } //************************************************************************** //** getDistinguishedFolderId //************************************************************************** /** Returns the DistinguishedFolderID for a given folder. */ public static String getDistinguishedFolderId(String folderName){ for (String folderID : DistinguishedFolderIds){ if (folderID.equalsIgnoreCase(folderName)) return folderID; } return null; } //************************************************************************** //** DistinguishedFolderIds //************************************************************************** /** Static list of Distinguished Folder IDs. Source: * http://msdn.microsoft.com/en-us/library/exchangewebservices.distinguishedfolderidnametype%28v=exchg.140%29.aspx */ private static String[] DistinguishedFolderIds = new String[]{ "archivedeleteditems", "archivemsgfolderroot", "archiverecoverableitemsdeletions", "archiverecoverableitemspurges", "archiverecoverableitemsroot", "archiverecoverableitemsversions", "archiveroot", "calendar", //Represents the Calendar folder. "contacts", //Represents the Contacts folder. "deleteditems", //Represents the Deleted Items folder. "drafts", //Represents the Drafts folder. "inbox", //Represents the Inbox folder. "journal", //Represents the Journal folder. "junkemail", //Represents the Junk E-mail folder. "msgfolderroot", //Represents the message folder root. "notes", //Represents the Notes folder. "outbox", //Represents the Outbox folder. "publicfoldersroot", "recoverableitemsdeletions", "recoverableitemspurges", "recoverableitemsroot", "recoverableitemsversions", "root", //Represents the root of the mailbox. "searchfolders", //Represents the Search Folders folder. This is also an alias for the Finder folder. "sentitems", //Represents the Sent Items folder. "tasks", //Represents the Tasks folder. "voicemail" //Represents the Voice Mail folder. }; } |