/*
* 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);
}
}
}