RegistrationManager.java 12.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/**
 * $Revision$
 * $Date$
 *
 * Copyright (C) 2006 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Public License (GPL),
 * a copy of which is included in this distribution.
 */

package org.jivesoftware.wildfire.gateway;

import org.xmpp.packet.JID;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.NotFoundException;
Matt Tucker's avatar
Matt Tucker committed
17
import org.picocontainer.Startable;
18 19 20 21 22 23 24 25

import java.util.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.ResultSet;

/**
26
 * Manages registration data for transports. Individual transports use the registration data
Matt Tucker's avatar
Matt Tucker committed
27
 * and then create sessions used to exchange messages and presence data.
28 29 30
 *
 * @author Matt Tucker
 */
Matt Tucker's avatar
Matt Tucker committed
31
public class RegistrationManager implements Startable {
32 33 34 35 36 37

    private static final String DELETE_REGISTRATION =
            "DELETE FROM gatewayRegistration WHERE registrationID=?";
    private static final String ALL_REGISTRATION_COUNT =
            "SELECT count(*) FROM gatewayRegistration";
    private static final String ALL_REGISTRATIONS =
38
            "SELECT registrationID FROM gatewayRegistration ORDER BY jid,transportType";
39
    private static final String LOAD_REGISTRATION =
40
            "SELECT registrationID FROM gatewayRegistration WHERE jid=? AND transportType=? AND username=?";
41
    private static final String ALL_USER_REGISTRATIONS =
42
            "SELECT registrationID FROM gatewayRegistration WHERE jid=? ORDER BY transportType";
43
    private static final String ALL_GATEWAY_REGISTRATIONS =
44
            "SELECT registrationID FROM gatewayRegistration WHERE transportType=? ORDER BY jid";
45
    private static final String USER_GATEWAY_REGISTRATIONS =
46
            "SELECT registrationID FROM gatewayRegistration WHERE jid=? AND transportType=?";
47 48
    private static final String DELETE_PSEUDO_ROSTER =
            "DELETE FROM gatewayPseudoRoster WHERE registrationID=?";
49

Matt Tucker's avatar
Matt Tucker committed
50 51 52 53 54 55 56 57
    public void start() {

    }

    public void stop() {

    }

58 59 60
    /**
     * Creates a new registration.
     *
Matt Tucker's avatar
Matt Tucker committed
61
     * @param jid the JID of the user making the registration.
62 63 64
     * @param transportType the type of the transport.
     * @param username the username on the transport service.
     * @param password the password on the transport service.
65
     * @param nickname the nickname on the transport service.
66 67
     * @return a new registration.
     */
68
    public Registration createRegistration(JID jid, TransportType transportType, String username,
69
            String password, String nickname)
70
    {
71
        return new Registration(jid, transportType, username, password, nickname);
72 73 74 75 76 77 78 79 80 81 82 83 84 85
    }

    /**
     * Deletes a registration.
     *
     * @param registration the registration to delete.
     */
    public void deleteRegistration(Registration registration) {
        Connection con = null;
        PreparedStatement pstmt = null;
        try {
            con = DbConnectionManager.getConnection();
            pstmt = con.prepareStatement(DELETE_REGISTRATION);
            pstmt.setLong(1, registration.getRegistrationID());
86
            pstmt.executeUpdate();
87 88 89 90

            pstmt = con.prepareStatement(DELETE_PSEUDO_ROSTER);
            pstmt.setLong(1, registration.getRegistrationID());
            pstmt.executeUpdate();
91 92 93 94 95 96 97 98 99
        }
        catch (SQLException sqle) {
            Log.error(sqle);
        }
        finally {
            DbConnectionManager.closeConnection(pstmt, con);
        }
    }

Matt Tucker's avatar
Matt Tucker committed
100
    /**
101
     * Returns all registrations for a particular type of transport.
Matt Tucker's avatar
Matt Tucker committed
102
     *
103 104
     * @param transportType the transport type.
     * @return all registrations for the transport type.
Matt Tucker's avatar
Matt Tucker committed
105
     */
106
    public Collection<Registration> getRegistrations(TransportType transportType) {
Matt Tucker's avatar
Matt Tucker committed
107 108 109 110 111 112 113
        List<Long> registrationIDs = new ArrayList<Long>();
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DbConnectionManager.getConnection();
            pstmt = con.prepareStatement(ALL_GATEWAY_REGISTRATIONS);
114
            pstmt.setString(1, transportType.name());
Matt Tucker's avatar
Matt Tucker committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
            rs = pstmt.executeQuery();
            while (rs.next()) {
                registrationIDs.add(rs.getLong(1));
            }
        }
        catch (SQLException sqle) {
            Log.error(sqle);
        }
        finally {
            DbConnectionManager.closeConnection(rs, pstmt, con);
        }
        if (registrationIDs.isEmpty()) {
            return Collections.emptyList();
        }
        else {
            return new RegistrationCollection(registrationIDs);
        }
132 133
    }

Matt Tucker's avatar
Matt Tucker committed
134 135 136 137 138 139
    /**
     * Returns all registrations for a particular JID.
     *
     * @param jid the JID of the user.
     * @return all registrations for the JID.
     */
Matt Tucker's avatar
Matt Tucker committed
140
    public Collection<Registration> getRegistrations(JID jid) {
Matt Tucker's avatar
Matt Tucker committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
        List<Long> registrationIDs = new ArrayList<Long>();
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DbConnectionManager.getConnection();
            pstmt = con.prepareStatement(ALL_USER_REGISTRATIONS);
            // Use the bare JID of the user.
            pstmt.setString(1, jid.toBareJID());
            rs = pstmt.executeQuery();
            while (rs.next()) {
                registrationIDs.add(rs.getLong(1));
            }
        }
        catch (SQLException sqle) {
            Log.error(sqle);
        }
        finally {
            DbConnectionManager.closeConnection(rs, pstmt, con);
        }
        if (registrationIDs.isEmpty()) {
            return Collections.emptyList();
        }
        else {
            return new RegistrationCollection(registrationIDs);
        }
167 168
    }

Matt Tucker's avatar
Matt Tucker committed
169
    /**
170 171
     * Returns all registrations that a JID has on a particular transport type.
     * In the typical case, a JID has a single registration with a particular transport
Matt Tucker's avatar
Matt Tucker committed
172 173
     * type. However, it's also possible to maintain multiple registrations. For example,
     * the user "joe_smith@example.com" might have have two user accounts on the AIM
174
     * transport service: "jsmith" and "joesmith".
Matt Tucker's avatar
Matt Tucker committed
175 176
     *
     * @param jid the JID of the user.
177 178
     * @param transportType the type of the transport.
     * @return all registrations for the JID of a particular transport type.
Matt Tucker's avatar
Matt Tucker committed
179
     */
180
    public Collection<Registration> getRegistrations(JID jid, TransportType transportType) {
Matt Tucker's avatar
Matt Tucker committed
181 182 183 184 185 186 187 188 189
        List<Long> registrationIDs = new ArrayList<Long>();
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DbConnectionManager.getConnection();
            pstmt = con.prepareStatement(USER_GATEWAY_REGISTRATIONS);
            // Use the bare JID of the user.
            pstmt.setString(1, jid.toBareJID());
190
            pstmt.setString(2, transportType.name());
Matt Tucker's avatar
Matt Tucker committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
            rs = pstmt.executeQuery();
            while (rs.next()) {
                registrationIDs.add(rs.getLong(1));
            }
        }
        catch (SQLException sqle) {
            Log.error(sqle);
        }
        finally {
            DbConnectionManager.closeConnection(rs, pstmt, con);
        }
        if (registrationIDs.isEmpty()) {
            return Collections.emptyList();
        }
        else {
            return new RegistrationCollection(registrationIDs);
        }
208 209
    }

Matt Tucker's avatar
Matt Tucker committed
210
    /**
211
     * Returns a registration given a JID, transport type, and username.
Matt Tucker's avatar
Matt Tucker committed
212 213
     *
     * @param jid the JID of the user.
214 215
     * @param transportType the transport type.
     * @param username the username on the transport service.
Matt Tucker's avatar
Matt Tucker committed
216 217 218
     * @return the registration.
     * @throws NotFoundException if the registration could not be found.
     */
219
    public Registration getRegistration(JID jid, TransportType transportType, String username)
220 221 222 223 224 225 226 227 228 229
            throws NotFoundException
    {
        long registrationID = -1;
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DbConnectionManager.getConnection();
            pstmt = con.prepareStatement(LOAD_REGISTRATION);
            pstmt.setString(1, jid.toBareJID());
230
            pstmt.setString(2, transportType.name());
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
            pstmt.setString(3, username);
            rs = pstmt.executeQuery();
            if (!rs.next()) {
                throw new NotFoundException("Could not load registration with ID " + registrationID);
            }
            registrationID = rs.getLong(1);
        }
        catch (SQLException sqle) {
            Log.error(sqle);
        }
        finally {
            DbConnectionManager.closeConnection(rs, pstmt, con);
        }
        return new Registration(registrationID);
    }

    /**
     * Returns the count of all registrations.
     *
     * @return the total count of registrations.
     */
    public int getRegistrationCount() {
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DbConnectionManager.getConnection();
            pstmt = con.prepareStatement(ALL_REGISTRATION_COUNT);
            rs = pstmt.executeQuery();
            rs.next();
            return rs.getInt(1);
        }
        catch (SQLException sqle) {
            Log.error(sqle);
        }
        finally {
            DbConnectionManager.closeConnection(rs, pstmt, con);
        }
        return 0;
    }

    /**
     * Returns all registrations.
     *
     * @return all registrations.
     */
    public Collection<Registration> getRegistrations() {
        List<Long> registrationIDs = new ArrayList<Long>();
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DbConnectionManager.getConnection();
            pstmt = con.prepareStatement(ALL_REGISTRATIONS);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                registrationIDs.add(rs.getLong(1));
            }
        }
        catch (SQLException sqle) {
            Log.error(sqle);
        }
        finally {
            DbConnectionManager.closeConnection(rs, pstmt, con);
        }
        if (registrationIDs.isEmpty()) {
            return Collections.emptyList();
        }
        else {
            return new RegistrationCollection(registrationIDs);
        }
    }

    /**
     * Converts a list of registration IDs into a Collection of Registrations.
     */
    private class RegistrationCollection extends AbstractCollection {

        private List<Long> registrationIDs;

        /**
         * Constructs a new query results object.
         *
         * @param registrationIDs the list of registration IDs.
         */
        public RegistrationCollection(List<Long> registrationIDs) {
            this.registrationIDs = registrationIDs;
        }

        public Iterator iterator() {
            final Iterator<Long> regIterator = registrationIDs.iterator();
            return new Iterator() {

                private Object nextElement = null;

                public boolean hasNext() {
                    if (nextElement == null) {
                        nextElement = getNextElement();
                        if (nextElement == null) {
                            return false;
                        }
                    }
                    return true;
                }

                public Object next() {
                    Object element;
                    if (nextElement != null) {
                        element = nextElement;
                        nextElement = null;
                    }
                    else {
                        element = getNextElement();
                        if (element == null) {
                            throw new NoSuchElementException();
                        }
                    }
                    return element;
                }

                public void remove() {
                    throw new UnsupportedOperationException();
                }

                private Object getNextElement() {
                    if (!regIterator.hasNext()) {
                        return null;
                    }
                    while (regIterator.hasNext()) {
                        try {
                            long registrationID = regIterator.next();
                            return new Registration(registrationID);
                        }
                        catch (Exception e) {
                            Log.error(e);
                        }
                    }
                    return null;
                }
            };
        }

        public int size() {
            return registrationIDs.size();
        }
    }
377
}