KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > messenger > roster > RosterItemProvider


1 /**
2  * $RCSfile: RosterItemProvider.java,v $
3  * $Revision: 1.5 $
4  * $Date: 2005/05/03 22:16:28 $
5  *
6  * Copyright (C) 2004 Jive Software. All rights reserved.
7  *
8  * This software is published under the terms of the GNU Public License (GPL),
9  * a copy of which is included in this distribution.
10  */

11
12 package org.jivesoftware.messenger.roster;
13
14 import org.jivesoftware.messenger.user.UserAlreadyExistsException;
15 import org.jivesoftware.messenger.user.UserNotFoundException;
16 import org.jivesoftware.database.DbConnectionManager;
17 import org.jivesoftware.database.SequenceManager;
18 import org.jivesoftware.util.JiveConstants;
19 import org.jivesoftware.util.Log;
20 import org.jivesoftware.util.LocaleUtils;
21 import org.xmpp.packet.JID;
22
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.LinkedList JavaDoc;
27 import java.sql.Connection JavaDoc;
28 import java.sql.PreparedStatement JavaDoc;
29 import java.sql.SQLException JavaDoc;
30 import java.sql.ResultSet JavaDoc;
31
32 /**
33  * <p>Defines the provider methods required for creating, reading, updating and deleting roster items.</p>
34  * <p/>
35  * <p>Rosters are another user resource accessed via the user or chatbot's long ID. A user/chatbot may have
36  * zero or more roster items and each roster item may have zero or more groups. Each roster item is
37  * additionaly keyed on a XMPP jid. In most cases, the entire roster will be read in from memory and manipulated
38  * or sent to the user. However some operations will need to retrive specific roster items rather than the
39  * entire roster.</p>
40  *
41  * @author Iain Shigeoka
42  */

43 public class RosterItemProvider {
44
45     private static final String JavaDoc CREATE_ROSTER_ITEM =
46             "INSERT INTO jiveRoster (username, rosterID, jid, sub, ask, recv, nick) " +
47             "VALUES (?, ?, ?, ?, ?, ?, ?)";
48     private static final String JavaDoc UPDATE_ROSTER_ITEM =
49             "UPDATE jiveRoster SET sub=?, ask=?, recv=?, nick=? WHERE rosterID=?";
50     private static final String JavaDoc DELETE_ROSTER_ITEM_GROUPS =
51             "DELETE FROM jiveRosterGroups WHERE rosterID=?";
52     private static final String JavaDoc CREATE_ROSTER_ITEM_GROUPS =
53             "INSERT INTO jiveRosterGroups (rosterID, rank, groupName) VALUES (?, ?, ?)";
54     private static final String JavaDoc DELETE_ROSTER_ITEM =
55             "DELETE FROM jiveRoster WHERE rosterID=?";
56     private static final String JavaDoc LOAD_USERNAMES =
57             "SELECT DISTINCT username from jiveRoster WHERE jid=?";
58     private static final String JavaDoc COUNT_ROSTER_ITEMS =
59             "SELECT COUNT(rosterID) FROM jiveRoster WHERE username=?";
60      private static final String JavaDoc LOAD_ROSTER =
61              "SELECT jid, rosterID, sub, ask, recv, nick FROM jiveRoster WHERE username=?";
62     private static final String JavaDoc LOAD_ROSTER_ITEM_GROUPS =
63             "SELECT groupName FROM jiveRosterGroups WHERE rosterID=? ORDER BY rank";
64
65
66     private static RosterItemProvider instance = new RosterItemProvider();
67
68     public static RosterItemProvider getInstance() {
69         return instance;
70     }
71
72     /**
73      * <p>Creates a new roster item for the given user (optional operation).</p>
74      * <p/>
75      * <p><b>Important!</b> The item passed as a parameter to this method is strictly a convenience for passing all
76      * of the data needed for a new roster item. The roster item returned from the method will be cached by Messenger.
77      * In some cases, the roster item passed in will be passed back out. However, if an implementation may
78      * return RosterItems as a separate class (for example, a RosterItem that directly accesses the backend
79      * storage, or one that is an object in an object database).
80      * <p/>
81      * <p>If you don't want roster items edited through messenger, throw UnsupportedOperationException.</p>
82      *
83      * @param username the username of the user/chatbot that owns the roster item
84      * @param item the settings for the roster item to create
85      * @return The created roster item
86      */

87     public RosterItem createItem(String JavaDoc username, RosterItem item)
88             throws UserAlreadyExistsException
89     {
90         Connection JavaDoc con = null;
91         PreparedStatement JavaDoc pstmt = null;
92         try {
93             con = DbConnectionManager.getConnection();
94
95             long rosterID = SequenceManager.nextID(JiveConstants.ROSTER);
96             pstmt = con.prepareStatement(CREATE_ROSTER_ITEM);
97             pstmt.setString(1, username);
98             pstmt.setLong(2, rosterID);
99             pstmt.setString(3, item.getJid().toBareJID());
100             pstmt.setInt(4, item.getSubStatus().getValue());
101             pstmt.setInt(5, item.getAskStatus().getValue());
102             pstmt.setInt(6, item.getRecvStatus().getValue());
103             pstmt.setString(7, item.getNickname());
104             pstmt.executeUpdate();
105
106             item.setID(rosterID);
107             insertGroups(rosterID, item.getGroups().iterator(), pstmt, con);
108         }
109         catch (SQLException JavaDoc e) {
110             throw new UserAlreadyExistsException(item.getJid().toBareJID());
111         }
112         finally {
113             try { if (pstmt != null) { pstmt.close(); } }
114             catch (Exception JavaDoc e) { Log.error(e); }
115             try { if (con != null) { con.close(); } }
116             catch (Exception JavaDoc e) { Log.error(e); }
117         }
118         return item;
119     }
120
121     /**
122      * <p>Update the roster item in storage with the information contained in the given item (optional operation).</p>
123      * <p/>
124      * <p>If you don't want roster items edited through messenger, throw UnsupportedOperationException.</p>
125      *
126      * @param username the username of the user/chatbot that owns the roster item
127      * @param item The roster item to update
128      * @throws org.jivesoftware.messenger.user.UserNotFoundException If no entry could be found to update
129      */

130     public void updateItem(String JavaDoc username, RosterItem item) throws UserNotFoundException {
131         Connection JavaDoc con = null;
132         PreparedStatement JavaDoc pstmt = null;
133         long rosterID = item.getID();
134         try {
135             con = DbConnectionManager.getConnection();
136             // Update existing roster item
137
pstmt = con.prepareStatement(UPDATE_ROSTER_ITEM);
138             pstmt.setInt(1, item.getSubStatus().getValue());
139             pstmt.setInt(2, item.getAskStatus().getValue());
140             pstmt.setInt(3, item.getRecvStatus().getValue());
141             pstmt.setString(4, item.getNickname());
142             pstmt.setLong(5, rosterID);
143             pstmt.executeUpdate();
144
145             // Delete old group list
146
pstmt = con.prepareStatement(DELETE_ROSTER_ITEM_GROUPS);
147             pstmt.setLong(1, rosterID);
148             pstmt.executeUpdate();
149
150             insertGroups(rosterID, item.getGroups().iterator(), pstmt, con);
151
152         }
153         catch (SQLException JavaDoc e) {
154             Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
155         }
156         finally {
157             try { if (pstmt != null) { pstmt.close(); } }
158             catch (Exception JavaDoc e) { Log.error(e); }
159             try { if (con != null) { con.close(); } }
160             catch (Exception JavaDoc e) { Log.error(e); }
161         }
162     }
163
164     /**
165      * <p>Delete the roster item with the given itemJID for the user (optional operation).</p>
166      * <p/>
167      * <p>If you don't want roster items deleted through messenger, throw UnsupportedOperationException.</p>
168      *
169      * @param username the long ID of the user/chatbot that owns the roster item
170      * @param rosterItemID The roster item to delete
171      */

172     public void deleteItem(String JavaDoc username, long rosterItemID) {
173         // Only try to remove the user if they exist in the roster already:
174
Connection JavaDoc con = null;
175         PreparedStatement JavaDoc pstmt = null;
176         try {
177             con = DbConnectionManager.getConnection();
178             // Remove roster groups
179
pstmt = con.prepareStatement(DELETE_ROSTER_ITEM_GROUPS);
180
181             pstmt.setLong(1, rosterItemID);
182             pstmt.executeUpdate();
183
184             // Remove roster
185
pstmt = con.prepareStatement(DELETE_ROSTER_ITEM);
186
187             pstmt.setLong(1, rosterItemID);
188             pstmt.executeUpdate();
189         }
190         catch (SQLException JavaDoc e) {
191             Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
192         }
193         finally {
194             try { if (pstmt != null) { pstmt.close(); } }
195             catch (Exception JavaDoc e) { Log.error(e); }
196             try { if (con != null) { con.close(); } }
197             catch (Exception JavaDoc e) { Log.error(e); }
198         }
199     }
200
201     /**
202      * Returns an iterator on the usernames whose roster includes the specified JID.
203      *
204      * @param jid the jid that the rosters should include.
205      * @return an iterator on the usernames whose roster includes the specified JID.
206      */

207     public Iterator JavaDoc<String JavaDoc> getUsernames(String JavaDoc jid) {
208         List JavaDoc<String JavaDoc> answer = new ArrayList JavaDoc<String JavaDoc>();
209         Connection JavaDoc con = null;
210         PreparedStatement JavaDoc pstmt = null;
211         try {
212             con = DbConnectionManager.getConnection();
213             pstmt = con.prepareStatement(LOAD_USERNAMES);
214             pstmt.setString(1, jid);
215             ResultSet JavaDoc rs = pstmt.executeQuery();
216             while (rs.next()) {
217                 answer.add(rs.getString(1));
218             }
219         }
220         catch (SQLException JavaDoc e) {
221             Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
222         }
223         finally {
224             try { if (pstmt != null) { pstmt.close(); } }
225             catch (Exception JavaDoc e) { Log.error(e); }
226             try { if (con != null) { con.close(); } }
227             catch (Exception JavaDoc e) { Log.error(e); }
228         }
229         return answer.iterator();
230     }
231
232     /**
233      * <p>Obtain a count of the number of roster items available for the given user.</p>
234      *
235      * @param username the username of the user/chatbot that owns the roster items
236      * @return The number of roster items available for the user
237      */

238     public int getItemCount(String JavaDoc username) {
239         int count = 0;
240         Connection JavaDoc con = null;
241         PreparedStatement JavaDoc pstmt = null;
242         try {
243             con = DbConnectionManager.getConnection();
244             pstmt = con.prepareStatement(COUNT_ROSTER_ITEMS);
245             pstmt.setString(1, username);
246             ResultSet JavaDoc rs = pstmt.executeQuery();
247             if (rs.next()) {
248                 count = rs.getInt(1);
249             }
250         }
251         catch (SQLException JavaDoc e) {
252             Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
253         }
254         finally {
255             try { if (pstmt != null) { pstmt.close(); } }
256             catch (Exception JavaDoc e) { Log.error(e); }
257             try { if (con != null) { con.close(); } }
258             catch (Exception JavaDoc e) { Log.error(e); }
259         }
260         return count;
261     }
262
263     /**
264      * <p>Retrieve an iterator of RosterItems for the given user.</p>
265      * <p/>
266      * <p>This method will commonly be called when a user logs in. The data will be cached
267      * in memory when possible. However, some rosters may be very large so items may need
268      * to be retrieved from the provider more frequently than usual for provider data.
269      *
270      * @param username the username of the user/chatbot that owns the roster items
271      * @return An iterator of all RosterItems owned by the user
272      */

273     public Iterator JavaDoc getItems(String JavaDoc username) {
274         LinkedList JavaDoc itemList = new LinkedList JavaDoc();
275         Connection JavaDoc con = null;
276         PreparedStatement JavaDoc pstmt = null;
277         try {
278             con = DbConnectionManager.getConnection();
279             pstmt = con.prepareStatement(LOAD_ROSTER);
280             pstmt.setString(1, username);
281             ResultSet JavaDoc rs = pstmt.executeQuery();
282             // TODO: this code must be refactored ASAP. Not legal to have two open pstmts
283
// TODO: on many databases.
284
while (rs.next()) {
285                 RosterItem item = new RosterItem(rs.getLong(2),
286                         new JID(rs.getString(1)),
287                         RosterItem.SubType.getTypeFromInt(rs.getInt(3)),
288                         RosterItem.AskType.getTypeFromInt(rs.getInt(4)),
289                         RosterItem.RecvType.getTypeFromInt(rs.getInt(5)),
290                         rs.getString(6),
291                         null);
292                 Connection JavaDoc con2 = DbConnectionManager.getConnection();
293                 PreparedStatement JavaDoc gstmt = null;
294                 ResultSet JavaDoc gs = null;
295                 try {
296                     gstmt = con2.prepareStatement(LOAD_ROSTER_ITEM_GROUPS);
297                     gstmt.setLong(1, item.getID());
298                     gs = gstmt.executeQuery();
299                     while (gs.next()) {
300                         item.getGroups().add(gs.getString(1));
301                     }
302                     itemList.add(item);
303                 }
304                 finally {
305                     try { if (gstmt != null) { gstmt.close(); } }
306                     catch (Exception JavaDoc e) { Log.error(e); }
307                     try { if (con2 != null) { con2.close(); } }
308                     catch (Exception JavaDoc e) { Log.error(e); }
309                 }
310             }
311         }
312         catch (SQLException JavaDoc e) {
313             Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
314         }
315         finally {
316             try { if (pstmt != null) { pstmt.close(); } }
317             catch (Exception JavaDoc e) { Log.error(e); }
318             try { if (con != null) { con.close(); } }
319             catch (Exception JavaDoc e) { Log.error(e); }
320         }
321         return itemList.iterator();
322     }
323
324     /**
325      * <p>Insert the groups into the given roster item.</p>
326      *
327      * @param rosterID The roster ID of the item the groups belong to
328      * @param iter An iterator over the group names to insert
329      */

330     private void insertGroups(long rosterID, Iterator JavaDoc iter, PreparedStatement JavaDoc pstmt,
331             Connection JavaDoc con) throws SQLException JavaDoc
332     {
333         try {
334             pstmt = con.prepareStatement(CREATE_ROSTER_ITEM_GROUPS);
335             pstmt.setLong(1, rosterID);
336             for (int i = 0; iter.hasNext(); i++) {
337                 pstmt.setInt(2, i);
338                 pstmt.setString(3, (String JavaDoc)iter.next());
339                 try {
340                     pstmt.executeUpdate();
341                 }
342                 catch (SQLException JavaDoc e) {
343                     Log.error(e);
344                 }
345             }
346         }
347         finally {
348             try {
349                 if (pstmt != null) {
350                     pstmt.close();
351                 }
352             }
353             catch (Exception JavaDoc e) {
354                 Log.error(e);
355             }
356         }
357     }
358 }
359
Popular Tags