/*
* Tigase Jabber/XMPP Server
* Copyright (C) 2004-2012 "Artur Hefczyc" <artur.hefczyc@tigase.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. Look for COPYING file in the top folder.
* If not, see http://www.gnu.org/licenses/.
*
* $Rev$
* Last modified by $Author$
* $Date$
*/
package tigase.server.ext;
//~--- non-JDK imports --------------------------------------------------------
import tigase.db.DataRepository;
import tigase.db.RepositoryFactory;
import tigase.db.comp.ComponentRepository;
import tigase.db.comp.RepositoryChangeListenerIfc;
import tigase.xml.DomBuilderHandler;
import tigase.xml.Element;
import tigase.xml.SimpleParser;
import tigase.xml.SingletonFactory;
import static tigase.conf.Configurable.*;
//~--- JDK imports ------------------------------------------------------------
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;
//~--- classes ----------------------------------------------------------------
/**
* Created: Nov 7, 2009 11:26:10 AM
*
* @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a>
* @version $Rev$
*/
public class CompSQLRepository implements ComponentRepository<CompRepoItem> {
/**
* Private logger for class instances.
*/
private static final Logger log = Logger.getLogger(CompSQLRepository.class.getName());
/** Field description */
public static final String REPO_URI_PROP_KEY = "repo-uri";
/** Field description */
public static final String TABLE_NAME = "external_component";
private static final String DOMAIN_COLUMN = "domain";
private static final String PASSWORD_COLUMN = "password";
private static final String CONNECTION_TYPE_COLUMN = "connection_type";
private static final String PORT_COLUMN = "port";
private static final String REMOTE_DOMAIN_COLUMN = "remote_domain";
private static final String PROTOCOL_COLUMN = "protocol";
private static final String OTHER_DATA_COLUMN = "other_data";
private static final String CREATE_TABLE_QUERY = "create table " + TABLE_NAME + " ("
+ " " + DOMAIN_COLUMN + " varchar(512) NOT NULL," + " " + PASSWORD_COLUMN
+ " varchar(255) NOT NULL," + " " + CONNECTION_TYPE_COLUMN + " varchar(127),"
+ " " + PORT_COLUMN + " int," + " " + REMOTE_DOMAIN_COLUMN + " varchar(1023),"
+ " " + PROTOCOL_COLUMN + " varchar(127)," + " " + OTHER_DATA_COLUMN
+ " varchar(32672)," + " primary key(" + DOMAIN_COLUMN + "))";
private static final String CHECK_TABLE_QUERY = "select count(*) from " + TABLE_NAME;
private static final String GET_ITEM_QUERY = "select * from " + TABLE_NAME
+ " where domain = ?";
private static final String ADD_ITEM_QUERY = "insert into " + TABLE_NAME + " ("
+ DOMAIN_COLUMN + ", " + PASSWORD_COLUMN + ", " + CONNECTION_TYPE_COLUMN + ", "
+ PORT_COLUMN + ", " + REMOTE_DOMAIN_COLUMN + ", " + PROTOCOL_COLUMN + ", "
+ OTHER_DATA_COLUMN + ") " + " values (?, ?, ?, ?, ?, ?, ?)";
private static final String DELETE_ITEM_QUERY = "delete from " + TABLE_NAME
+ " where (domain = ?)";
private static final String GET_ALL_ITEMS_QUERY = "select * from " + TABLE_NAME;
private DataRepository data_repo = null;
// private PreparedStatement addItemSt = null;
// private PreparedStatement checkTableSt = null;
// private PreparedStatement createTableSt = null;
// private PreparedStatement deleteItemSt = null;
// private PreparedStatement getAllItemsSt = null;
// private PreparedStatement getItemSt = null;
private String tableName = TABLE_NAME;
private CompConfigRepository configRepo = new CompConfigRepository();
@Override
public void addRepoChangeListener(
RepositoryChangeListenerIfc<CompRepoItem> repoChangeListener) {
configRepo.addRepoChangeListener(repoChangeListener);
}
@Override
public void removeRepoChangeListener(
RepositoryChangeListenerIfc<CompRepoItem> repoChangeListener) {
configRepo.removeRepoChangeListener(repoChangeListener);
}
/**
* Method description
*
*
* @param item
*/
@Override
public void addItem(CompRepoItem item) {
try {
PreparedStatement addItemSt = data_repo.getPreparedStatement(null, ADD_ITEM_QUERY);
synchronized (addItemSt) {
if ((item.getDomain() != null) && !item.getDomain().isEmpty()) {
addItemSt.setString(1, item.getDomain());
} else {
throw new NullPointerException("Null or empty domain name is not allowed");
}
if (item.getAuthPasswd() != null) {
addItemSt.setString(2, item.getAuthPasswd());
} else {
throw new NullPointerException("Null password is not allowed");
}
if (item.getConnectionType() != null) {
addItemSt.setString(3, item.getConnectionType().name());
} else {
addItemSt.setNull(3, Types.VARCHAR);
}
if (item.getPort() > 0) {
addItemSt.setInt(4, item.getPort());
} else {
addItemSt.setNull(4, Types.INTEGER);
}
if ((item.getRemoteHost() != null) && !item.getRemoteHost().isEmpty()) {
addItemSt.setString(5, item.getRemoteHost());
} else {
addItemSt.setNull(5, Types.VARCHAR);
}
if (item.getXMLNS() != null) {
addItemSt.setString(6, item.getXMLNS());
} else {
addItemSt.setNull(6, Types.VARCHAR);
}
String other_data = item.toElement().toString();
if (other_data != null) {
addItemSt.setString(7, other_data);
} else {
addItemSt.setNull(7, Types.VARCHAR);
}
addItemSt.executeUpdate();
}
} catch (SQLException e) {
log.log(Level.WARNING, "Problem adding a new item to DB: " + item.toElement(), e);
}
}
/**
* Method description
*
*
* @return
*/
@Override
public Collection<CompRepoItem> allItems() {
List<CompRepoItem> result = new ArrayList<CompRepoItem>();
result.addAll(configRepo.allItems());
ResultSet rs = null;
try {
PreparedStatement getAllItemsSt =
data_repo.getPreparedStatement(null, GET_ALL_ITEMS_QUERY);
synchronized (getAllItemsSt) {
rs = getAllItemsSt.executeQuery();
while (rs.next()) {
result.add(createItemFromRS(rs));
}
}
} catch (SQLException e) {
log.log(Level.WARNING, "Problem getting elements from DB: ", e);
} finally {
data_repo.release(null, rs);
}
return result;
}
/**
* Method description
*
*
* @param key
*
* @return
*/
@Override
public boolean contains(String key) {
boolean result = configRepo.contains(key);
return result;
}
// ~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param defs
* @param params
*/
@Override
public void getDefaults(Map<String, Object> defs, Map<String, Object> params) {
configRepo.getDefaults(defs, params);
String repo_uri = DERBY_REPO_URL_PROP_VAL;
if (params.get(GEN_USER_DB_URI) != null) {
repo_uri = (String) params.get(GEN_USER_DB_URI);
}
defs.put(REPO_URI_PROP_KEY, repo_uri);
}
/**
* Method description
*
*
* @param key
*
* @return
*/
@Override
public CompRepoItem getItem(String key) {
CompRepoItem result = configRepo.getItem(key);
if (result == null) {
ResultSet rs = null;
try {
PreparedStatement getItemSt =
data_repo.getPreparedStatement(null, GET_ITEM_QUERY);
synchronized (getItemSt) {
getItemSt.setString(1, key);
rs = getItemSt.executeQuery();
if (rs.next()) {
result = createItemFromRS(rs);
}
}
} catch (SQLException e) {
log.log(Level.WARNING, "Problem getting element from DB for domain: " + key, e);
} finally {
data_repo.release(null, rs);
}
}
return result;
}
/**
* Method description
*
*
* @return
*/
@Override
public CompRepoItem getItemInstance() {
return configRepo.getItemInstance();
}
// ~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param conn_str
* @param params
*
* @throws SQLException
*/
public void initRepository(String conn_str, Map<String, String> params)
throws SQLException {
try {
data_repo = RepositoryFactory.getDataRepository(null, conn_str, params);
checkDB();
data_repo.initPreparedStatement(CHECK_TABLE_QUERY, CHECK_TABLE_QUERY);
data_repo.initPreparedStatement(GET_ITEM_QUERY, GET_ITEM_QUERY);
data_repo.initPreparedStatement(GET_ALL_ITEMS_QUERY, GET_ALL_ITEMS_QUERY);
data_repo.initPreparedStatement(ADD_ITEM_QUERY, ADD_ITEM_QUERY);
data_repo.initPreparedStatement(DELETE_ITEM_QUERY, DELETE_ITEM_QUERY);
} catch (Exception e) {
// Do nothing for now...
} finally {
// Check if DB is correctly setup and contains all required tables.
}
}
/**
* Method description
*
*
* @return
*/
@Override
public Iterator<CompRepoItem> iterator() {
return allItems().iterator();
}
/**
* Method description
*
*/
@Override
public void reload() {
// Do nothing, no caching, everything is read on demand from DB
}
/**
* Method description
*
*
* @param key
*/
@Override
public void removeItem(String key) {
configRepo.removeItem(key);
try {
PreparedStatement deleteItemSt =
data_repo.getPreparedStatement(null, DELETE_ITEM_QUERY);
synchronized (deleteItemSt) {
deleteItemSt.setString(1, key);
deleteItemSt.executeUpdate();
}
} catch (SQLException e) {
log.log(Level.WARNING, "Can't remove item: " + key, e);
}
}
// ~--- set methods ----------------------------------------------------------
/**
* Method description
*
*
* @param properties
*/
@Override
public void setProperties(Map<String, Object> properties) {
configRepo.setProperties(properties);
String repo_uri = (String) properties.get(REPO_URI_PROP_KEY);
try {
initRepository(repo_uri, null);
} catch (SQLException ex) {
log.log(Level.WARNING, "Problem initializing database.", ex);
}
}
// ~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
public int size() {
int result = configRepo.size();
return result;
}
/**
* Method description
*
*/
@Override
public void store() {
// Do nothing everything is written on demand to DB
}
/**
* Method description
*
*
* @param item
*
* @return
*/
@Override
public String validateItem(CompRepoItem item) {
return null;
}
private void checkDB() throws SQLException {
ResultSet rs = null;
Statement st = null;
try {
if (!data_repo.checkTable(tableName)) {
log.info("DB for external component is not OK, creating missing tables...");
st = data_repo.createStatement(null);
st.executeUpdate(CREATE_TABLE_QUERY);
log.info("DB for external component created OK");
}
} finally {
data_repo.release(st, rs);
rs = null;
st = null;
}
}
private CompRepoItem createItemFromRS(ResultSet rs) throws SQLException {
CompRepoItem result = getItemInstance();
// First init from other parameters, some fixed fields may
// overwrite fields initialized from other parametrs
String other = rs.getString(OTHER_DATA_COLUMN);
if ((other != null) && !other.isEmpty()) {
Element elem_item = parseElement(other);
if (elem_item != null) {
result.initFromElement(elem_item);
}
}
String domain = rs.getString(DOMAIN_COLUMN);
if ((domain != null) && !domain.isEmpty()) {
result.setDomain(domain);
}
String password = rs.getString(PASSWORD_COLUMN);
if ((password != null) && !password.isEmpty()) {
result.setPassword(password);
}
int port = rs.getInt(PORT_COLUMN);
if (port > 0) {
result.setPort(port);
}
String remote_domain = rs.getString(REMOTE_DOMAIN_COLUMN);
if ((remote_domain != null) && !remote_domain.isEmpty()) {
result.setRemoteDomain(remote_domain);
}
String protocol = rs.getString(PROTOCOL_COLUMN);
if ((protocol != null) && !protocol.isEmpty()) {
result.setProtocol(protocol);
}
String connection_type = rs.getString(CONNECTION_TYPE_COLUMN);
if ((connection_type != null) && !connection_type.isEmpty()) {
result.setConnectionType(connection_type);
}
return result;
}
private Element parseElement(String data) {
DomBuilderHandler domHandler = new DomBuilderHandler();
SimpleParser parser = SingletonFactory.getParserInstance();
parser.parse(domHandler, data.toCharArray(), 0, data.length());
Queue<Element> elems = domHandler.getParsedElements();
if ((elems != null) && (elems.size() > 0)) {
return elems.poll();
}
return null;
}
}
// ~ Formatted in Sun Code Convention
// ~ Formatted by Jindent --- http://www.jindent.com