/* * Copyright 2006-2010 Daniel Henninger. 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 net.sf.kraken.registration; import net.sf.kraken.type.TransportType; import org.apache.log4j.Logger; import org.jivesoftware.database.DbConnectionManager; import org.jivesoftware.database.JiveID; import org.jivesoftware.database.SequenceManager; import org.jivesoftware.openfire.auth.AuthFactory; import org.jivesoftware.util.NotFoundException; import org.xmpp.packet.JID; import java.sql.*; import java.util.Date; /** * Contains information about the registration a user has made with an external transport. * Each registration includes a username and password used to login to the transport * as well as a registration date and last login date.<p> * * The password for the transport registration is stored in encrypted form using * the Openfire password encryption key. See {@link org.jivesoftware.openfire.auth.AuthFactory#encryptPassword(String)}. * * @author Matt Tucker */ @JiveID(125) public class Registration { static Logger Log = Logger.getLogger(Registration.class); private static final String INSERT_REGISTRATION = "INSERT INTO ofGatewayRegistration(registrationID, jid, transportType, " + "username, password, nickname, registrationDate) VALUES (?,?,?,?,?,?,?)"; private static final String LOAD_REGISTRATION = "SELECT jid, transportType, username, password, nickname, registrationDate, lastLogin " + "FROM ofGatewayRegistration WHERE registrationID=?"; private static final String SET_LAST_LOGIN = "UPDATE ofGatewayRegistration SET lastLogin=? WHERE registrationID=?"; private static final String SET_PASSWORD = "UPDATE ofGatewayRegistration SET password=? WHERE registrationID=?"; private static final String SET_USERNAME = "UPDATE ofGatewayRegistration SET username=? WHERE registrationID=?"; private static final String SET_NICKNAME = "UPDATE ofGatewayRegistration SET nickname=? WHERE registrationID=?"; private long registrationID; private JID jid; private TransportType transportType; private String username; private String password; private String nickname; private Date registrationDate; private Date lastLogin; private boolean disconnectedMode = false; /** * Do not use, only for clustering support/externalizable. */ public Registration() { } /** * Creates a new registration. * * @param jid the JID of the user making the registration. * @param transportType the type of the transport. * @param username the username on the transport. * @param password the password on the transport. * @param nickname the nickname on the transport. */ public Registration(JID jid, TransportType transportType, String username, String password, String nickname) { if (jid == null || transportType == null || username == null) { throw new NullPointerException("Arguments cannot be null."); } // Ensure that we store the bare JID. this.jid = new JID(jid.toBareJID()); this.transportType = transportType; this.username = username; this.password = password; this.nickname = nickname; this.registrationDate = new Date(); try { insertIntoDb(); } catch (Exception e) { Log.error(e); } } /** * Creates a new registration in disconnected (test) mode. * * Passing false for disconnectedMode is the same as the previous constructor. * * @param jid the JID of the user making the registration. * @param transportType the type of the transport. * @param username the username on the transport. * @param password the password on the transport. * @param nickname the nickname on the transport. * @param disconnectedMode True or false if we are in disconnected mode. */ public Registration(JID jid, TransportType transportType, String username, String password, String nickname, Boolean disconnectedMode) { if (jid == null || transportType == null || username == null) { throw new NullPointerException("Arguments cannot be null."); } this.disconnectedMode = disconnectedMode; // Ensure that we store the bare JID. this.jid = new JID(jid.toBareJID()); this.transportType = transportType; this.username = username; this.password = password; this.nickname = nickname; this.registrationDate = new Date(); try { insertIntoDb(); } catch (Exception e) { Log.error(e); } } /** * Loads an existing registration. * * @param registrationID the ID of the registration. * @throws org.jivesoftware.util.NotFoundException if the registration could not be loaded. */ public Registration(long registrationID) throws NotFoundException { this.registrationID = registrationID; loadFromDb(); } /** * Returns the unique ID of the registration. * * @return the registration ID. */ public long getRegistrationID() { return registrationID; } /** * Returns the JID of the user that made this registration. * * @return the JID of the user. */ public JID getJID() { return jid; } /** * Returns the type of the transport. * * @return the transport type. */ public TransportType getTransportType() { return transportType; } /** * Returns the username used for logging in to the transport. * * @return the username. */ public String getUsername() { return username; } /** * Returns the password used for logging in to the transport. * * @return the password. */ public String getPassword() { return password; } /** * Returns the nickname used for logging in to the transport. * * @return the nickname. */ public String getNickname() { return nickname; } /** * Sets the password used for logging in to the transport. * * @param password new password for registration. */ public void setPassword(String password) { this.password = password; if (disconnectedMode) { return; } // The password is stored in encrypted form for improved security. String encryptedPassword = AuthFactory.encryptPassword(password); Connection con = null; PreparedStatement pstmt = null; try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(SET_PASSWORD); if (password != null) { pstmt.setString(1, encryptedPassword); } else { pstmt.setNull(1, Types.VARCHAR); } pstmt.setLong(2, registrationID); pstmt.executeUpdate(); } catch (SQLException sqle) { Log.error(sqle); } finally { DbConnectionManager.closeConnection(pstmt, con); } } /** * Sets the username used for logging in to the transport. * * @param username New username for transport registration. */ public void setUsername(String username) { if (username == null) { throw new NullPointerException("Arguments cannot be null."); } this.username = username; if (disconnectedMode) { return; } Connection con = null; PreparedStatement pstmt = null; try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(SET_USERNAME); pstmt.setString(1, username); pstmt.setLong(2, registrationID); pstmt.executeUpdate(); } catch (SQLException sqle) { Log.error(sqle); } finally { DbConnectionManager.closeConnection(pstmt, con); } } /** * Sets the nickname used for logging in to the transport. * * @param nickname New nickname for transport registration. */ public void setNickname(String nickname) { this.nickname = nickname; if (disconnectedMode) { return; } Connection con = null; PreparedStatement pstmt = null; try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(SET_NICKNAME); if (nickname != null) { pstmt.setString(1, nickname); } else { pstmt.setNull(1, Types.VARCHAR); } pstmt.setLong(2, registrationID); pstmt.executeUpdate(); } catch (SQLException sqle) { Log.error(sqle); } finally { DbConnectionManager.closeConnection(pstmt, con); } } /** * Returns the date that this transport registration was created. * * @return the date the registration was created. */ public Date getRegistrationDate() { return registrationDate; } /** * Returns the date that the user last logged in to the transport using this * registration data, or <tt>null</tt> if the user has never logged in. * * @return the last login date. */ public Date getLastLogin() { return lastLogin; } /** * Sets the data that the user last logged into the transport. * * @param lastLogin the last login date. */ public void setLastLogin(Date lastLogin) { this.lastLogin = lastLogin; if (disconnectedMode) { return; } Connection con = null; PreparedStatement pstmt = null; try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(SET_LAST_LOGIN); pstmt.setLong(1, lastLogin.getTime()); pstmt.setLong(2, registrationID); pstmt.executeUpdate(); } catch (SQLException sqle) { Log.error(sqle); } finally { DbConnectionManager.closeConnection(pstmt, con); } } @Override public String toString() { return jid + ", " + transportType + ", " + username; } /** * Inserts a new registration into the database. * * @throws SQLException if the SQL statement is wrong for whatever reason. */ private void insertIntoDb() throws SQLException { if (disconnectedMode) { return; } this.registrationID = SequenceManager.nextID(this); Connection con = null; PreparedStatement pstmt = null; boolean abortTransaction = false; try { con = DbConnectionManager.getTransactionConnection(); pstmt = con.prepareStatement(INSERT_REGISTRATION); pstmt.setLong(1, registrationID); pstmt.setString(2, jid.toString()); pstmt.setString(3, transportType.name()); pstmt.setString(4, username); if (password != null) { // The password is stored in encrypted form for improved security. String encryptedPassword = AuthFactory.encryptPassword(password); pstmt.setString(5, encryptedPassword); } else { pstmt.setNull(5, Types.VARCHAR); } if (nickname != null) { pstmt.setString(6, nickname); } else { pstmt.setNull(6, Types.VARCHAR); } pstmt.setLong(7, registrationDate.getTime()); pstmt.executeUpdate(); } catch (SQLException sqle) { abortTransaction = true; throw sqle; } finally { DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction); } } /** * Load registration from database. * * @throws NotFoundException if registration was not found in database. */ private void loadFromDb() throws NotFoundException { if (disconnectedMode) { return; } Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(LOAD_REGISTRATION); pstmt.setLong(1, registrationID); rs = pstmt.executeQuery(); if (!rs.next()) { throw new NotFoundException("Registration not found: " + registrationID); } this.jid = new JID(rs.getString(1)); this.transportType = TransportType.valueOf(rs.getString(2)); this.username = rs.getString(3); // The password is stored in encrypted form, so decrypt it. this.password = AuthFactory.decryptPassword(rs.getString(4)); this.nickname = rs.getString(5); this.registrationDate = new Date(rs.getLong(6)); long loginDate = rs.getLong(7); if (rs.wasNull()) { this.lastLogin = null; } else { this.lastLogin = new Date(loginDate); } } catch (SQLException sqle) { Log.error(sqle); } finally { DbConnectionManager.closeConnection(rs, pstmt, con); } } }