
com.samskivert.servlet.JDBCTableSiteIdentifier Maven / Gradle / Ivy
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001-2011 Michael Bayne, et al.
// http://github.com/samskivert/samskivert/blob/master/COPYING
package com.samskivert.servlet;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import com.samskivert.io.PersistenceException;
import com.samskivert.jdbc.ConnectionProvider;
import com.samskivert.jdbc.DatabaseLiaison;
import com.samskivert.jdbc.JDBCUtil;
import com.samskivert.jdbc.SimpleRepository;
import com.samskivert.util.ArrayUtil;
import com.samskivert.util.HashIntMap;
import static com.samskivert.Log.log;
/**
* Accomplishes the process of site identification based on a mapping from domains (e.g.
* samskivert.com) to site identifiers that is maintained in a database table, accessible via JDBC
* (hence the name).
*
* There are two tables, one that maps domains to site identifiers and another that maps site
* identifiers to site strings. These are both loaded at construct time and refreshed periodically
* in the course of normal operation.
*
*
Note that any of the calls to identify, lookup or enumerate site information can result in
* the sites table being refreshed from the database which will take relatively much longer than
* the simple hashtable lookup that the operations normally require. However, this happens only
* once every 15 minutes and the circumstances in which the site identifier are normally used can
* generally accomodate the extra 100 milliseconds or so that it is likely to take to reload the
* (tiny) sites and domains tables from the database.
*/
public class JDBCTableSiteIdentifier implements SiteIdentifier
{
/** The database identifier used to obtain a connection from our connection provider. The value
* is sitedb
which you'll probably need to know to provide the proper
* configuration to your connection provider. */
public static final String SITE_IDENTIFIER_IDENT = "sitedb";
/**
* Constructs a JDBC table site identifier with the supplied connection provider from which to
* obtain its database connection.
*
* @see #SITE_IDENTIFIER_IDENT
*/
public JDBCTableSiteIdentifier (ConnectionProvider conprov)
throws PersistenceException
{
this(conprov, DEFAULT_SITE_ID);
}
/**
* Creates an identifier that will load data from the supplied connection provider and which
* will use the supplied default site id instead of {@link #DEFAULT_SITE_ID}.
*/
public JDBCTableSiteIdentifier (ConnectionProvider conprov, int defaultSiteId)
throws PersistenceException
{
_repo = new SiteIdentifierRepository(conprov);
_repo.refreshSiteData();
_defaultSiteId = defaultSiteId;
}
// documentation inherited
public int identifySite (HttpServletRequest req)
{
checkReloadSites();
String serverName = req.getServerName();
// scan for the mapping that matches the specified domain
int msize = _mappings.size();
for (int i = 0; i < msize; i++) {
SiteMapping mapping = _mappings.get(i);
if (serverName.endsWith(mapping.domain)) {
return mapping.siteId;
}
}
// if we matched nothing, return the default id
return _defaultSiteId;
}
// documentation inherited
public String getSiteString (int siteId)
{
checkReloadSites();
Site site = _sitesById.get(siteId);
if (site == null) {
site = _sitesById.get(_defaultSiteId);
}
return (site == null) ? DEFAULT_SITE_STRING : site.siteString;
}
// documentation inherited
public int getSiteId (String siteString)
{
checkReloadSites();
Site site = _sitesByString.get(siteString);
return (site == null) ? _defaultSiteId : site.siteId;
}
// documentation inherited from interface
public Iterator enumerateSites ()
{
checkReloadSites();
return _sitesById.values().iterator();
}
/**
* Insert a new site into the site table and into this mapping.
*/
public Site insertNewSite (String siteString)
throws PersistenceException
{
if (_sitesByString.containsKey(siteString)) {
return null;
}
// add it to the db
Site site = new Site();
site.siteString = siteString;
_repo.insertNewSite(site);
// add it to our two mapping tables, taking care to avoid causing enumerateSites() to choke
@SuppressWarnings("unchecked") HashMap newStrings =
(HashMap)_sitesByString.clone();
HashIntMap newIds = _sitesById.clone();
newIds.put(site.siteId, site);
newStrings.put(site.siteString, site);
_sitesByString = newStrings;
_sitesById = newIds;
return site;
}
/**
* Checks to see if we should reload our sites information from the sites table.
*/
protected void checkReloadSites ()
{
long now = System.currentTimeMillis();
boolean reload = false;
synchronized (this) {
reload = (now - _lastReload > RELOAD_INTERVAL);
if (reload) {
_lastReload = now;
}
}
if (reload) {
try {
_repo.refreshSiteData();
} catch (PersistenceException pe) {
log.warning("Error refreshing site data.", pe);
}
}
}
/**
* Used to load information from the site database.
*/
protected class SiteIdentifierRepository extends SimpleRepository
implements SimpleRepository.Operation