001/* 002 * 003 * Copyright 2003-2007 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.bookmarks; 018 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.List; 022 023import org.jivesoftware.smack.util.ParserUtils; 024import org.jivesoftware.smack.util.XmlStringBuilder; 025import org.jivesoftware.smack.xml.XmlPullParser; 026import org.jivesoftware.smack.xml.XmlPullParserException; 027 028import org.jivesoftware.smackx.iqprivate.packet.PrivateData; 029import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; 030 031import org.jxmpp.JxmppContext; 032import org.jxmpp.jid.EntityBareJid; 033import org.jxmpp.jid.parts.Resourcepart; 034 035/** 036 * Bookmarks is used for storing and retrieving URLS and Conference rooms. 037 * Bookmark Storage (XEP-0048) defined a protocol for the storage of bookmarks to conference rooms and other entities 038 * in a Jabber user's account. 039 * See the following code sample for saving Bookmarks: 040 * <pre> 041 * XMPPConnection con = new XMPPTCPConnection("jabber.org"); 042 * con.login("john", "doe"); 043 * Bookmarks bookmarks = new Bookmarks(); 044 * // Bookmark a URL 045 * BookmarkedURL url = new BookmarkedURL(); 046 * url.setName("Google"); 047 * url.setURL("http://www.jivesoftware.com"); 048 * bookmarks.addURL(url); 049 * // Bookmark a Conference room. 050 * BookmarkedConference conference = new BookmarkedConference(); 051 * conference.setName("My Favorite Room"); 052 * conference.setAutoJoin("true"); 053 * conference.setJID("dev@conference.jivesoftware.com"); 054 * bookmarks.addConference(conference); 055 * // Save Bookmarks using PrivateDataManager. 056 * PrivateDataManager manager = new PrivateDataManager(con); 057 * manager.setPrivateData(bookmarks); 058 * LastActivity activity = LastActivity.getLastActivity(con, "xray@jabber.org"); 059 * </pre> 060 * 061 * @author Derek DeMoro 062 */ 063public class Bookmarks implements PrivateData { 064 065 public static final String NAMESPACE = "storage:bookmarks"; 066 public static final String ELEMENT = "storage"; 067 068 private final List<BookmarkedURL> bookmarkedURLS; 069 private final List<BookmarkedConference> bookmarkedConferences; 070 071 /** 072 * Required Empty Constructor to use Bookmarks. 073 */ 074 public Bookmarks() { 075 bookmarkedURLS = new ArrayList<>(); 076 bookmarkedConferences = new ArrayList<>(); 077 } 078 079 /** 080 * Adds a BookmarkedURL. 081 * 082 * @param bookmarkedURL the bookmarked bookmarkedURL. 083 */ 084 public void addBookmarkedURL(BookmarkedURL bookmarkedURL) { 085 bookmarkedURLS.add(bookmarkedURL); 086 } 087 088 /** 089 * Removes a bookmarked bookmarkedURL. 090 * 091 * @param bookmarkedURL the bookmarked bookmarkedURL to remove. 092 */ 093 public void removeBookmarkedURL(BookmarkedURL bookmarkedURL) { 094 bookmarkedURLS.remove(bookmarkedURL); 095 } 096 097 /** 098 * Removes all BookmarkedURLs from user's bookmarks. 099 */ 100 public void clearBookmarkedURLS() { 101 bookmarkedURLS.clear(); 102 } 103 104 /** 105 * Add a BookmarkedConference to bookmarks. 106 * 107 * @param bookmarkedConference the conference to remove. 108 */ 109 public void addBookmarkedConference(BookmarkedConference bookmarkedConference) { 110 bookmarkedConferences.add(bookmarkedConference); 111 } 112 113 /** 114 * Removes a BookmarkedConference. 115 * 116 * @param bookmarkedConference the BookmarkedConference to remove. 117 */ 118 public void removeBookmarkedConference(BookmarkedConference bookmarkedConference) { 119 bookmarkedConferences.remove(bookmarkedConference); 120 } 121 122 /** 123 * Removes all BookmarkedConferences from Bookmarks. 124 */ 125 public void clearBookmarkedConferences() { 126 bookmarkedConferences.clear(); 127 } 128 129 /** 130 * Returns a Collection of all Bookmarked URLs for this user. 131 * 132 * @return a collection of all Bookmarked URLs. 133 */ 134 public List<BookmarkedURL> getBookmarkedURLS() { 135 return bookmarkedURLS; 136 } 137 138 /** 139 * Returns a Collection of all Bookmarked Conference for this user. 140 * 141 * @return a collection of all Bookmarked Conferences. 142 */ 143 public List<BookmarkedConference> getBookmarkedConferences() { 144 return bookmarkedConferences; 145 } 146 147 148 /** 149 * Returns the root element name. 150 * 151 * @return the element name. 152 */ 153 @Override 154 public String getElementName() { 155 return ELEMENT; 156 } 157 158 /** 159 * Returns the root element XML namespace. 160 * 161 * @return the namespace. 162 */ 163 @Override 164 public String getNamespace() { 165 return NAMESPACE; 166 } 167 168 /** 169 * Returns the XML representation of the PrivateData. 170 * 171 * @return the private data as XML. 172 */ 173 @Override 174 public XmlStringBuilder toXML() { 175 XmlStringBuilder buf = new XmlStringBuilder(); 176 buf.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket(); 177 178 for (BookmarkedURL urlStorage : getBookmarkedURLS()) { 179 if (urlStorage.isShared()) { 180 continue; 181 } 182 buf.halfOpenElement("url").attribute("name", urlStorage.getName()).attribute("url", urlStorage.getURL()); 183 buf.condAttribute(urlStorage.isRss(), "rss", "true"); 184 buf.closeEmptyElement(); 185 } 186 187 // Add Conference additions 188 for (BookmarkedConference conference : getBookmarkedConferences()) { 189 if (conference.isShared()) { 190 continue; 191 } 192 buf.halfOpenElement("conference"); 193 buf.attribute("name", conference.getName()); 194 buf.attribute("autojoin", Boolean.toString(conference.isAutoJoin())); 195 buf.attribute("jid", conference.getJid()); 196 buf.rightAngleBracket(); 197 198 buf.optElement("nick", conference.getNickname()); 199 buf.optElement("password", conference.getPassword()); 200 201 buf.closeElement("conference"); 202 } 203 204 buf.closeElement(ELEMENT); 205 return buf; 206 } 207 208 /** 209 * The IQ Provider for BookmarkStorage. 210 * 211 * @author Derek DeMoro 212 */ 213 public static class Provider implements PrivateDataProvider { 214 215 /** 216 * Empty Constructor for PrivateDataProvider. 217 */ 218 public Provider() { 219 super(); 220 } 221 222 @Override 223 public PrivateData parsePrivateData(XmlPullParser parser, JxmppContext jxmppContext) throws XmlPullParserException, IOException { 224 Bookmarks storage = new Bookmarks(); 225 226 boolean done = false; 227 while (!done) { 228 XmlPullParser.Event eventType = parser.next(); 229 if (eventType == XmlPullParser.Event.START_ELEMENT && "url".equals(parser.getName())) { 230 final BookmarkedURL urlStorage = getURLStorage(parser); 231 if (urlStorage != null) { 232 storage.addBookmarkedURL(urlStorage); 233 } 234 } 235 else if (eventType == XmlPullParser.Event.START_ELEMENT && 236 "conference".equals(parser.getName())) { 237 final BookmarkedConference conference = getConferenceStorage(parser, jxmppContext); 238 storage.addBookmarkedConference(conference); 239 } 240 else if (eventType == XmlPullParser.Event.END_ELEMENT && "storage".equals(parser.getName())) { 241 done = true; 242 } 243 } 244 245 246 return storage; 247 } 248 } 249 250 private static BookmarkedURL getURLStorage(XmlPullParser parser) throws IOException, XmlPullParserException { 251 String name = parser.getAttributeValue("", "name"); 252 String url = parser.getAttributeValue("", "url"); 253 String rssString = parser.getAttributeValue("", "rss"); 254 boolean rss = rssString != null && "true".equals(rssString); 255 256 BookmarkedURL urlStore = new BookmarkedURL(url, name, rss); 257 boolean done = false; 258 while (!done) { 259 XmlPullParser.Event eventType = parser.next(); 260 if (eventType == XmlPullParser.Event.START_ELEMENT 261 && "shared_bookmark".equals(parser.getName())) { 262 urlStore.setShared(true); 263 } 264 else if (eventType == XmlPullParser.Event.END_ELEMENT && "url".equals(parser.getName())) { 265 done = true; 266 } 267 } 268 return urlStore; 269 } 270 271 private static BookmarkedConference getConferenceStorage(XmlPullParser parser, JxmppContext jxmppContext) throws XmlPullParserException, IOException { 272 String name = parser.getAttributeValue("", "name"); 273 boolean autojoin = ParserUtils.getBooleanAttribute(parser, "autojoin", false); 274 EntityBareJid jid = ParserUtils.getBareJidAttribute(parser, jxmppContext); 275 276 BookmarkedConference conf = new BookmarkedConference(jid); 277 conf.setName(name); 278 conf.setAutoJoin(autojoin); 279 280 // Check for nickname 281 boolean done = false; 282 while (!done) { 283 XmlPullParser.Event eventType = parser.next(); 284 if (eventType == XmlPullParser.Event.START_ELEMENT && "nick".equals(parser.getName())) { 285 String nickString = parser.nextText(); 286 conf.setNickname(Resourcepart.from(nickString)); 287 } 288 else if (eventType == XmlPullParser.Event.START_ELEMENT && "password".equals(parser.getName())) { 289 conf.setPassword(parser.nextText()); 290 } 291 else if (eventType == XmlPullParser.Event.START_ELEMENT 292 && "shared_bookmark".equals(parser.getName())) { 293 conf.setShared(true); 294 } 295 else if (eventType == XmlPullParser.Event.END_ELEMENT && "conference".equals(parser.getName())) { 296 done = true; 297 } 298 } 299 300 301 return conf; 302 } 303}