diff options
Diffstat (limited to 'src/org/jivesoftware/smackx/bookmark')
5 files changed, 803 insertions, 0 deletions
diff --git a/src/org/jivesoftware/smackx/bookmark/BookmarkManager.java b/src/org/jivesoftware/smackx/bookmark/BookmarkManager.java new file mode 100644 index 0000000..f85cc9c --- /dev/null +++ b/src/org/jivesoftware/smackx/bookmark/BookmarkManager.java @@ -0,0 +1,224 @@ +/** + * $Revision$ + * $Date$ + * + * Copyright 2003-2007 Jive Software. + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.bookmark; + +import org.jivesoftware.smack.Connection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.PrivateDataManager; + +import java.util.*; + +/** + * Provides methods to manage bookmarks in accordance with JEP-0048. Methods for managing URLs and + * Conferences are provided. + * </p> + * It should be noted that some extensions have been made to the JEP. There is an attribute on URLs + * that marks a url as a news feed and also a sub-element can be added to either a URL or conference + * indicated that it is shared amongst all users on a server. + * + * @author Alexander Wenckus + */ +public class BookmarkManager { + private static final Map<Connection, BookmarkManager> bookmarkManagerMap = new HashMap<Connection, BookmarkManager>(); + static { + PrivateDataManager.addPrivateDataProvider("storage", "storage:bookmarks", + new Bookmarks.Provider()); + } + + /** + * Returns the <i>BookmarkManager</i> for a connection, if it doesn't exist it is created. + * + * @param connection the connection for which the manager is desired. + * @return Returns the <i>BookmarkManager</i> for a connection, if it doesn't + * exist it is created. + * @throws XMPPException Thrown if the connection is null or has not yet been authenticated. + */ + public synchronized static BookmarkManager getBookmarkManager(Connection connection) + throws XMPPException + { + BookmarkManager manager = (BookmarkManager) bookmarkManagerMap.get(connection); + if(manager == null) { + manager = new BookmarkManager(connection); + bookmarkManagerMap.put(connection, manager); + } + return manager; + } + + private PrivateDataManager privateDataManager; + private Bookmarks bookmarks; + private final Object bookmarkLock = new Object(); + + /** + * Default constructor. Registers the data provider with the private data manager in the + * storage:bookmarks namespace. + * + * @param connection the connection for persisting and retrieving bookmarks. + * @throws XMPPException thrown when the connection is null or has not been authenticated. + */ + private BookmarkManager(Connection connection) throws XMPPException { + if(connection == null || !connection.isAuthenticated()) { + throw new XMPPException("Invalid connection."); + } + this.privateDataManager = new PrivateDataManager(connection); + } + + /** + * Returns all currently bookmarked conferences. + * + * @return returns all currently bookmarked conferences + * @throws XMPPException thrown when there was an error retrieving the current bookmarks from + * the server. + * @see BookmarkedConference + */ + public Collection<BookmarkedConference> getBookmarkedConferences() throws XMPPException { + retrieveBookmarks(); + return Collections.unmodifiableCollection(bookmarks.getBookmarkedConferences()); + } + + /** + * Adds or updates a conference in the bookmarks. + * + * @param name the name of the conference + * @param jid the jid of the conference + * @param isAutoJoin whether or not to join this conference automatically on login + * @param nickname the nickname to use for the user when joining the conference + * @param password the password to use for the user when joining the conference + * @throws XMPPException thrown when there is an issue retrieving the current bookmarks from + * the server. + */ + public void addBookmarkedConference(String name, String jid, boolean isAutoJoin, + String nickname, String password) throws XMPPException + { + retrieveBookmarks(); + BookmarkedConference bookmark + = new BookmarkedConference(name, jid, isAutoJoin, nickname, password); + List<BookmarkedConference> conferences = bookmarks.getBookmarkedConferences(); + if(conferences.contains(bookmark)) { + BookmarkedConference oldConference = conferences.get(conferences.indexOf(bookmark)); + if(oldConference.isShared()) { + throw new IllegalArgumentException("Cannot modify shared bookmark"); + } + oldConference.setAutoJoin(isAutoJoin); + oldConference.setName(name); + oldConference.setNickname(nickname); + oldConference.setPassword(password); + } + else { + bookmarks.addBookmarkedConference(bookmark); + } + privateDataManager.setPrivateData(bookmarks); + } + + /** + * Removes a conference from the bookmarks. + * + * @param jid the jid of the conference to be removed. + * @throws XMPPException thrown when there is a problem with the connection attempting to + * retrieve the bookmarks or persist the bookmarks. + * @throws IllegalArgumentException thrown when the conference being removed is a shared + * conference + */ + public void removeBookmarkedConference(String jid) throws XMPPException { + retrieveBookmarks(); + Iterator<BookmarkedConference> it = bookmarks.getBookmarkedConferences().iterator(); + while(it.hasNext()) { + BookmarkedConference conference = it.next(); + if(conference.getJid().equalsIgnoreCase(jid)) { + if(conference.isShared()) { + throw new IllegalArgumentException("Conference is shared and can't be removed"); + } + it.remove(); + privateDataManager.setPrivateData(bookmarks); + return; + } + } + } + + /** + * Returns an unmodifiable collection of all bookmarked urls. + * + * @return returns an unmodifiable collection of all bookmarked urls. + * @throws XMPPException thrown when there is a problem retriving bookmarks from the server. + */ + public Collection<BookmarkedURL> getBookmarkedURLs() throws XMPPException { + retrieveBookmarks(); + return Collections.unmodifiableCollection(bookmarks.getBookmarkedURLS()); + } + + /** + * Adds a new url or updates an already existing url in the bookmarks. + * + * @param URL the url of the bookmark + * @param name the name of the bookmark + * @param isRSS whether or not the url is an rss feed + * @throws XMPPException thrown when there is an error retriving or saving bookmarks from or to + * the server + */ + public void addBookmarkedURL(String URL, String name, boolean isRSS) throws XMPPException { + retrieveBookmarks(); + BookmarkedURL bookmark = new BookmarkedURL(URL, name, isRSS); + List<BookmarkedURL> urls = bookmarks.getBookmarkedURLS(); + if(urls.contains(bookmark)) { + BookmarkedURL oldURL = urls.get(urls.indexOf(bookmark)); + if(oldURL.isShared()) { + throw new IllegalArgumentException("Cannot modify shared bookmarks"); + } + oldURL.setName(name); + oldURL.setRss(isRSS); + } + else { + bookmarks.addBookmarkedURL(bookmark); + } + privateDataManager.setPrivateData(bookmarks); + } + + /** + * Removes a url from the bookmarks. + * + * @param bookmarkURL the url of the bookmark to remove + * @throws XMPPException thrown if there is an error retriving or saving bookmarks from or to + * the server. + */ + public void removeBookmarkedURL(String bookmarkURL) throws XMPPException { + retrieveBookmarks(); + Iterator<BookmarkedURL> it = bookmarks.getBookmarkedURLS().iterator(); + while(it.hasNext()) { + BookmarkedURL bookmark = it.next(); + if(bookmark.getURL().equalsIgnoreCase(bookmarkURL)) { + if(bookmark.isShared()) { + throw new IllegalArgumentException("Cannot delete a shared bookmark."); + } + it.remove(); + privateDataManager.setPrivateData(bookmarks); + return; + } + } + } + + private Bookmarks retrieveBookmarks() throws XMPPException { + synchronized(bookmarkLock) { + if(bookmarks == null) { + bookmarks = (Bookmarks) privateDataManager.getPrivateData("storage", + "storage:bookmarks"); + } + return bookmarks; + } + } +} diff --git a/src/org/jivesoftware/smackx/bookmark/BookmarkedConference.java b/src/org/jivesoftware/smackx/bookmark/BookmarkedConference.java new file mode 100644 index 0000000..5dac202 --- /dev/null +++ b/src/org/jivesoftware/smackx/bookmark/BookmarkedConference.java @@ -0,0 +1,130 @@ +/** + * $Revision$ + * $Date$ + * + * Copyright 2003-2007 Jive Software. + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.bookmark; + +/** + * Respresents a Conference Room bookmarked on the server using JEP-0048 Bookmark Storage JEP. + * + * @author Derek DeMoro + */ +public class BookmarkedConference implements SharedBookmark { + + private String name; + private boolean autoJoin; + private final String jid; + + private String nickname; + private String password; + private boolean isShared; + + protected BookmarkedConference(String jid) { + this.jid = jid; + } + + protected BookmarkedConference(String name, String jid, boolean autoJoin, String nickname, + String password) + { + this.name = name; + this.jid = jid; + this.autoJoin = autoJoin; + this.nickname = nickname; + this.password = password; + } + + + /** + * Returns the display label representing the Conference room. + * + * @return the name of the conference room. + */ + public String getName() { + return name; + } + + protected void setName(String name) { + this.name = name; + } + + /** + * Returns true if this conference room should be auto-joined on startup. + * + * @return true if room should be joined on startup, otherwise false. + */ + public boolean isAutoJoin() { + return autoJoin; + } + + protected void setAutoJoin(boolean autoJoin) { + this.autoJoin = autoJoin; + } + + /** + * Returns the full JID of this conference room. (ex.dev@conference.jivesoftware.com) + * + * @return the full JID of this conference room. + */ + public String getJid() { + return jid; + } + + /** + * Returns the nickname to use when joining this conference room. This is an optional + * value and may return null. + * + * @return the nickname to use when joining, null may be returned. + */ + public String getNickname() { + return nickname; + } + + protected void setNickname(String nickname) { + this.nickname = nickname; + } + + /** + * Returns the password to use when joining this conference room. This is an optional + * value and may return null. + * + * @return the password to use when joining this conference room, null may be returned. + */ + public String getPassword() { + return password; + } + + protected void setPassword(String password) { + this.password = password; + } + + public boolean equals(Object obj) { + if(obj == null || !(obj instanceof BookmarkedConference)) { + return false; + } + BookmarkedConference conference = (BookmarkedConference)obj; + return conference.getJid().equalsIgnoreCase(jid); + } + + protected void setShared(boolean isShared) { + this.isShared = isShared; + } + + public boolean isShared() { + return isShared; + } +} diff --git a/src/org/jivesoftware/smackx/bookmark/BookmarkedURL.java b/src/org/jivesoftware/smackx/bookmark/BookmarkedURL.java new file mode 100644 index 0000000..f3d6d9d --- /dev/null +++ b/src/org/jivesoftware/smackx/bookmark/BookmarkedURL.java @@ -0,0 +1,104 @@ +/** + * $Revision$ + * $Date$ + * + * Copyright 2003-2007 Jive Software. + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.bookmark; + +/** + * Respresents one instance of a URL defined using JEP-0048 Bookmark Storage JEP. + * + * @author Derek DeMoro + */ +public class BookmarkedURL implements SharedBookmark { + + private String name; + private final String URL; + private boolean isRss; + private boolean isShared; + + protected BookmarkedURL(String URL) { + this.URL = URL; + } + + protected BookmarkedURL(String URL, String name, boolean isRss) { + this.URL = URL; + this.name = name; + this.isRss = isRss; + } + + /** + * Returns the name representing the URL (eg. Jive Software). This can be used in as a label, or + * identifer in applications. + * + * @return the name reprenting the URL. + */ + public String getName() { + return name; + } + + /** + * Sets the name representing the URL. + * + * @param name the name. + */ + protected void setName(String name) { + this.name = name; + } + + /** + * Returns the URL. + * + * @return the url. + */ + public String getURL() { + return URL; + } + /** + * Set to true if this URL is an RSS or news feed. + * + * @param isRss True if the URL is a news feed and false if it is not. + */ + protected void setRss(boolean isRss) { + this.isRss = isRss; + } + + /** + * Returns true if this URL is a news feed. + * + * @return Returns true if this URL is a news feed. + */ + public boolean isRss() { + return isRss; + } + + public boolean equals(Object obj) { + if(!(obj instanceof BookmarkedURL)) { + return false; + } + BookmarkedURL url = (BookmarkedURL)obj; + return url.getURL().equalsIgnoreCase(URL); + } + + protected void setShared(boolean shared) { + this.isShared = shared; + } + + public boolean isShared() { + return isShared; + } +} diff --git a/src/org/jivesoftware/smackx/bookmark/Bookmarks.java b/src/org/jivesoftware/smackx/bookmark/Bookmarks.java new file mode 100644 index 0000000..100fa46 --- /dev/null +++ b/src/org/jivesoftware/smackx/bookmark/Bookmarks.java @@ -0,0 +1,310 @@ +/** + * $Revision$ + * $Date$ + * + * Copyright 2003-2007 Jive Software. + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smackx.bookmark; + +import org.jivesoftware.smackx.packet.PrivateData; +import org.jivesoftware.smackx.provider.PrivateDataProvider; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Bookmarks is used for storing and retrieving URLS and Conference rooms. + * Bookmark Storage (JEP-0048) defined a protocol for the storage of bookmarks to conference rooms and other entities + * in a Jabber user's account. + * See the following code sample for saving Bookmarks: + * <p/> + * <pre> + * Connection con = new XMPPConnection("jabber.org"); + * con.login("john", "doe"); + * Bookmarks bookmarks = new Bookmarks(); + * <p/> + * // Bookmark a URL + * BookmarkedURL url = new BookmarkedURL(); + * url.setName("Google"); + * url.setURL("http://www.jivesoftware.com"); + * bookmarks.addURL(url); + * // Bookmark a Conference room. + * BookmarkedConference conference = new BookmarkedConference(); + * conference.setName("My Favorite Room"); + * conference.setAutoJoin("true"); + * conference.setJID("dev@conference.jivesoftware.com"); + * bookmarks.addConference(conference); + * // Save Bookmarks using PrivateDataManager. + * PrivateDataManager manager = new PrivateDataManager(con); + * manager.setPrivateData(bookmarks); + * <p/> + * <p/> + * LastActivity activity = LastActivity.getLastActivity(con, "xray@jabber.org"); + * </pre> + * + * @author Derek DeMoro + */ +public class Bookmarks implements PrivateData { + + private List<BookmarkedURL> bookmarkedURLS; + private List<BookmarkedConference> bookmarkedConferences; + + /** + * Required Empty Constructor to use Bookmarks. + */ + public Bookmarks() { + bookmarkedURLS = new ArrayList<BookmarkedURL>(); + bookmarkedConferences = new ArrayList<BookmarkedConference>(); + } + + /** + * Adds a BookmarkedURL. + * + * @param bookmarkedURL the bookmarked bookmarkedURL. + */ + public void addBookmarkedURL(BookmarkedURL bookmarkedURL) { + bookmarkedURLS.add(bookmarkedURL); + } + + /** + * Removes a bookmarked bookmarkedURL. + * + * @param bookmarkedURL the bookmarked bookmarkedURL to remove. + */ + public void removeBookmarkedURL(BookmarkedURL bookmarkedURL) { + bookmarkedURLS.remove(bookmarkedURL); + } + + /** + * Removes all BookmarkedURLs from user's bookmarks. + */ + public void clearBookmarkedURLS() { + bookmarkedURLS.clear(); + } + + /** + * Add a BookmarkedConference to bookmarks. + * + * @param bookmarkedConference the conference to remove. + */ + public void addBookmarkedConference(BookmarkedConference bookmarkedConference) { + bookmarkedConferences.add(bookmarkedConference); + } + + /** + * Removes a BookmarkedConference. + * + * @param bookmarkedConference the BookmarkedConference to remove. + */ + public void removeBookmarkedConference(BookmarkedConference bookmarkedConference) { + bookmarkedConferences.remove(bookmarkedConference); + } + + /** + * Removes all BookmarkedConferences from Bookmarks. + */ + public void clearBookmarkedConferences() { + bookmarkedConferences.clear(); + } + + /** + * Returns a Collection of all Bookmarked URLs for this user. + * + * @return a collection of all Bookmarked URLs. + */ + public List<BookmarkedURL> getBookmarkedURLS() { + return bookmarkedURLS; + } + + /** + * Returns a Collection of all Bookmarked Conference for this user. + * + * @return a collection of all Bookmarked Conferences. + */ + public List<BookmarkedConference> getBookmarkedConferences() { + return bookmarkedConferences; + } + + + /** + * Returns the root element name. + * + * @return the element name. + */ + public String getElementName() { + return "storage"; + } + + /** + * Returns the root element XML namespace. + * + * @return the namespace. + */ + public String getNamespace() { + return "storage:bookmarks"; + } + + /** + * Returns the XML reppresentation of the PrivateData. + * + * @return the private data as XML. + */ + public String toXML() { + StringBuilder buf = new StringBuilder(); + buf.append("<storage xmlns=\"storage:bookmarks\">"); + + final Iterator<BookmarkedURL> urls = getBookmarkedURLS().iterator(); + while (urls.hasNext()) { + BookmarkedURL urlStorage = urls.next(); + if(urlStorage.isShared()) { + continue; + } + buf.append("<url name=\"").append(urlStorage.getName()). + append("\" url=\"").append(urlStorage.getURL()).append("\""); + if(urlStorage.isRss()) { + buf.append(" rss=\"").append(true).append("\""); + } + buf.append(" />"); + } + + // Add Conference additions + final Iterator<BookmarkedConference> conferences = getBookmarkedConferences().iterator(); + while (conferences.hasNext()) { + BookmarkedConference conference = conferences.next(); + if(conference.isShared()) { + continue; + } + buf.append("<conference "); + buf.append("name=\"").append(conference.getName()).append("\" "); + buf.append("autojoin=\"").append(conference.isAutoJoin()).append("\" "); + buf.append("jid=\"").append(conference.getJid()).append("\" "); + buf.append(">"); + + if (conference.getNickname() != null) { + buf.append("<nick>").append(conference.getNickname()).append("</nick>"); + } + + + if (conference.getPassword() != null) { + buf.append("<password>").append(conference.getPassword()).append("</password>"); + } + buf.append("</conference>"); + } + + + buf.append("</storage>"); + return buf.toString(); + } + + /** + * The IQ Provider for BookmarkStorage. + * + * @author Derek DeMoro + */ + public static class Provider implements PrivateDataProvider { + + /** + * Empty Constructor for PrivateDataProvider. + */ + public Provider() { + super(); + } + + public PrivateData parsePrivateData(XmlPullParser parser) throws Exception { + Bookmarks storage = new Bookmarks(); + + boolean done = false; + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG && "url".equals(parser.getName())) { + final BookmarkedURL urlStorage = getURLStorage(parser); + if (urlStorage != null) { + storage.addBookmarkedURL(urlStorage); + } + } + else if (eventType == XmlPullParser.START_TAG && + "conference".equals(parser.getName())) + { + final BookmarkedConference conference = getConferenceStorage(parser); + storage.addBookmarkedConference(conference); + } + else if (eventType == XmlPullParser.END_TAG && "storage".equals(parser.getName())) + { + done = true; + } + } + + + return storage; + } + } + + private static BookmarkedURL getURLStorage(XmlPullParser parser) throws IOException, XmlPullParserException { + String name = parser.getAttributeValue("", "name"); + String url = parser.getAttributeValue("", "url"); + String rssString = parser.getAttributeValue("", "rss"); + boolean rss = rssString != null && "true".equals(rssString); + + BookmarkedURL urlStore = new BookmarkedURL(url, name, rss); + boolean done = false; + while (!done) { + int eventType = parser.next(); + if(eventType == XmlPullParser.START_TAG + && "shared_bookmark".equals(parser.getName())) { + urlStore.setShared(true); + } + else if (eventType == XmlPullParser.END_TAG && "url".equals(parser.getName())) { + done = true; + } + } + return urlStore; + } + + private static BookmarkedConference getConferenceStorage(XmlPullParser parser) throws Exception { + String name = parser.getAttributeValue("", "name"); + String autojoin = parser.getAttributeValue("", "autojoin"); + String jid = parser.getAttributeValue("", "jid"); + + BookmarkedConference conf = new BookmarkedConference(jid); + conf.setName(name); + conf.setAutoJoin(Boolean.valueOf(autojoin).booleanValue()); + + // Check for nickname + boolean done = false; + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG && "nick".equals(parser.getName())) { + conf.setNickname(parser.nextText()); + } + else if (eventType == XmlPullParser.START_TAG && "password".equals(parser.getName())) { + conf.setPassword(parser.nextText()); + } + else if(eventType == XmlPullParser.START_TAG + && "shared_bookmark".equals(parser.getName())) { + conf.setShared(true); + } + else if (eventType == XmlPullParser.END_TAG && "conference".equals(parser.getName())) { + done = true; + } + } + + + return conf; + } +} diff --git a/src/org/jivesoftware/smackx/bookmark/SharedBookmark.java b/src/org/jivesoftware/smackx/bookmark/SharedBookmark.java new file mode 100644 index 0000000..f672bc1 --- /dev/null +++ b/src/org/jivesoftware/smackx/bookmark/SharedBookmark.java @@ -0,0 +1,35 @@ +/** + * $Revision$ + * $Date$ + * + * Copyright 2003-2007 Jive Software. + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.bookmark; + +/** + * Interface to indicate if a bookmark is shared across the server. + * + * @author Alexander Wenckus + */ +public interface SharedBookmark { + + /** + * Returns true if this bookmark is shared. + * + * @return returns true if this bookmark is shared. + */ + public boolean isShared(); +} |