/*
* Copyright 2000-2001,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jetspeed.services.psmlmanager.db;
import java.sql.Connection;
// PSML Manager Service interface
import org.apache.jetspeed.services.psmlmanager.PsmlManagerService;
// Jetspeed Security service
import org.apache.jetspeed.services.JetspeedSecurity;
// Profile and ProfileLocator interface
import org.apache.jetspeed.om.profile.Profile;
import org.apache.jetspeed.om.profile.ProfileLocator;
import org.apache.jetspeed.om.profile.QueryLocator;
import org.apache.jetspeed.services.Profiler;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
//Castor defined API
import org.apache.jetspeed.om.profile.Portlets;
import org.apache.jetspeed.om.profile.PSMLDocument;
import org.apache.jetspeed.om.profile.BasePSMLDocument;
//turbine stuff
import org.apache.turbine.services.TurbineBaseService;
import org.apache.turbine.services.InitializationException;
import org.apache.turbine.services.TurbineServices;
import org.apache.turbine.services.resources.ResourceService;
import org.apache.turbine.services.servlet.TurbineServlet;
import org.apache.turbine.services.servlet.ServletService;
// torque
import org.apache.torque.Torque;
// jetspeed security
import org.apache.jetspeed.om.security.JetspeedUser;
import org.apache.jetspeed.om.security.JetspeedUserFactory;
import org.apache.jetspeed.om.security.Role;
import org.apache.jetspeed.om.security.JetspeedRoleFactory;
import org.apache.jetspeed.om.security.Group;
import org.apache.jetspeed.om.security.JetspeedGroupFactory;
import org.apache.jetspeed.services.security.JetspeedSecurityException;
//Servlet API
import javax.servlet.ServletConfig;
// Torque generated classes
import org.apache.jetspeed.om.dbpsml.JetspeedUserProfile;
import org.apache.jetspeed.om.dbpsml.JetspeedUserProfilePeer;
import org.apache.jetspeed.om.dbpsml.JetspeedRoleProfile;
import org.apache.jetspeed.om.dbpsml.JetspeedRoleProfilePeer;
import org.apache.jetspeed.om.dbpsml.JetspeedGroupProfile;
import org.apache.jetspeed.om.dbpsml.JetspeedGroupProfilePeer;
//standard java stuff
import java.lang.Thread;
import java.util.List;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.io.FileReader;
import java.io.File;
import org.exolab.castor.mapping.Mapping;
import org.xml.sax.InputSource;
/**
* This service is responsible for loading and saving PSML documents. It uses
* database to persist the PSML documents.
*
* @author <a href="mailto:adambalk@cisco.com">Atul Dambalkar</a>
* @author <a href="mailto:mvaidya@cisco.com">Medha Vaidya</a>
* @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
* @version $Id: DatabasePsmlManagerService.java,v 1.35 2004/02/23 03:32:19 jford Exp $
*/
public class DatabasePsmlManagerService extends TurbineBaseService
implements DatabasePsmlManager
{
/**
* Static initialization of the logger for this class
*/
private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(DatabasePsmlManagerService.class.getName());
private Map psmlCache = new HashMap();
/** The watcher for the document locations */
private CacheRefresher refresher = null;
/** the base refresh rate for documents */
private long refreshRate; // default will be 8 hours
private final static String REFRESH_RATE = "refresh-rate";
private final static long DEFAULT_REFRESH_RATE = 60 * 60 * 8 * 1000; //8hrs
/** whether caching is allowed */
private boolean cachingOn; // default will be false
private final static String CACHING_ON = "caching-on";
private final static boolean DEFAULT_CACHING_ON = false;
private final static String POOL_NAME = "database";
/** the import/export consumer service **/
private PsmlManagerService consumer = null;
// castor mapping
public static final String DEFAULT_MAPPING = "${webappRoot}/WEB-INF/conf/psml-mapping.xml";
String mapFile = null;
/** the Castor mapping file name */
private Mapping mapping = null;
/** The pool name to use for database requests. */
private String poolName = null;
/**
* This is the early initialization method called by the
* Turbine <code>Service</code> framework
*/
public void init(ServletConfig conf) throws InitializationException
{
if (getInit())
{
return;
}
logger.info("Initializing DatabasePsmlManagerService...");
initConfiguration(conf);
logger.info("Done initializing DatabasePsmlManagerService.");
}
/**
* Loads the configuration parameters for this service from the
* JetspeedResources.properties file.
*
* @exception throws a <code>InitializationException</code> if the service
* fails to initialize
*/
private void initConfiguration(ServletConfig conf)
throws InitializationException
{
//Ensure that the servlet service is initialized
TurbineServices.getInstance().initService(ServletService.SERVICE_NAME, conf);
ResourceService serviceConf =
((TurbineServices)TurbineServices.getInstance())
.getResources(PsmlManagerService.SERVICE_NAME);
try
{
// get configuration parameters from Turbine Resources
// we'll use only string accessors so the values can be multiply
// specified in the properties files (the first one wins).
String value = serviceConf.getString(REFRESH_RATE);
refreshRate = DEFAULT_REFRESH_RATE;
try
{
refreshRate = Long.parseLong(value);
}
catch (Exception e)
{
logger.warn("DatabasePsmlManagerService: error in refresh-rate configuration: using default");
}
// get the name of the torque database pool to use
poolName = serviceConf.getString(POOL_NAME);
//find out if caching allowed
value = serviceConf.getString(CACHING_ON);
cachingOn = DEFAULT_CACHING_ON;
try
{
cachingOn = value.equals("true");
}
catch (Exception e)
{
logger.warn("DatabasePsmlManagerService: error in caching-on configuration: using default");
}
// psml castor mapping file
mapFile = serviceConf.getString("mapping",DEFAULT_MAPPING);
mapFile = TurbineServlet.getRealPath( mapFile );
loadMapping();
}
catch (Throwable t)
{
logger.error(this + ".init:" , t);
throw new InitializationException("Exception initializing DatabasePsmlManagerService" + t);
}
if (cachingOn)
{
this.refresher = new CacheRefresher();
refresher.start();
}
}
/** Late init method from Turbine Service model */
public void init() throws InitializationException
{
//Mark that we are done
setInit(true);
/*
try
{
PsmlImporter importer = new PsmlImporter();
importer.run(null);
}
catch (Exception e)
{
logger.warn("DatabasePsmlManagerService.init: exception while importing:" , e);
}
*/
}
protected void loadMapping()
throws InitializationException
{
// test the mapping file and create the mapping object
if (mapFile != null)
{
File map = new File(mapFile);
if (logger.isDebugEnabled())
logger.debug("Loading psml mapping file " + mapFile);
if (map.exists() && map.isFile() && map.canRead())
{
try
{
mapping = new Mapping();
InputSource is = new InputSource( new FileReader(map) );
is.setSystemId( mapFile );
mapping.loadMapping( is );
}
catch (Exception e)
{
logger.error("Error in psml mapping creation",e);
throw new InitializationException("Error in mapping",e);
}
}
else
{
throw new InitializationException("PSML Mapping not found or not a file or unreadable: "+mapFile);
}
}
}
/**
* This is the shutdown method called by the
* Turbine <code>Service</code> framework
*/
public void shutdown()
{
if (this.refresher != null)
{
this.refresher.setDone(true);
}
}
/**
* A thread implementation of cache refreshing mechanism for database
* persisted PSMLs. We have to refresh the cache after specific intervals
* if someone manually updates the PSML database.
*
* @author <a href="mailto:adambalk@cisco.com">Atul Dambalkar</a>
*/
class CacheRefresher extends Thread
{
private boolean done = false;
/**
* Constructor to to set the priority.
*/
CacheRefresher()
{
setDaemon(true);
setPriority(Thread.MIN_PRIORITY+1);
}
/**
* We are all done, system is shutting down.
*/
void setDone(boolean done)
{
this.done = done;
}
/**
* Method as needed for a Thread to run
*/
public void run()
{
try
{
while (!done)
{
if (logger.isDebugEnabled())
logger.debug("Cache Refresher thread sleeping now!");
sleep (refreshRate);
if (logger.isDebugEnabled())
logger.debug("Cache Refresher thread working now!");
try
{
synchronized (this)
{
Iterator i = psmlCache.keySet().iterator();
while(i.hasNext())
{
String locator = (String)i.next();
// do refresh for the locator
PSMLDocument doc =
refresh(stringToLocator(locator));
// over write the existing document in cache
psmlCache.put(locator, doc);
}
}
}
catch (Exception e)
{
logger.warn("DatabasePsmlManagerService.CacheRefresher: Error in cache refresher...", e);
}
}
}
catch (InterruptedException e)
{
if (logger.isDebugEnabled())
logger.debug("DatabasePsmlManagerService.CacheRefresher: recieved interruption, aborting.");
}
}
}
/**
* Return a unique string identifying this object.
*/
private String locatorToString(ProfileLocator locator)
{
StringBuffer keybuf = new StringBuffer();
JetspeedUser user = locator.getUser();
Role role = locator.getRole();
Group group = locator.getGroup();
String name = locator.getName();
String mediaType = locator.getMediaType();
String country = locator.getCountry();
String language = locator.getLanguage();
synchronized (this)
{
if (user != null)
{
keybuf.append("User:").append(user.getUserName());
}
else if (group != null)
{
keybuf.append("Group:").append(group.getName());
}
else if (role != null)
{
keybuf.append("Role:").append(role.getName());
}
if (name != null)
{
keybuf.append('$').append("Page:").append(name);
}
if (mediaType != null)
{
keybuf.append('$').append("MediaType:").append(mediaType);
}
if (country != null && (! country.equals("-1")))
{
keybuf.append('$').append("Country:").append(country);
}
if (language != null && (! language.equals("-1")))
{
keybuf.append('$').append("Language:").append(language);
}
}
if (logger.isDebugEnabled())
logger.debug("DatabasePsmlManagerService: Returning locator string: " + keybuf.toString());
return keybuf.toString();
}
private ProfileLocator stringToLocator(String locstr) throws Exception
{
ProfileLocator locator = Profiler.createLocator();
String entity = null;
if (logger.isDebugEnabled())
logger.debug("DatabasePsmlManagerService: Creating locator for string: " + locstr);
StringTokenizer dollarTokens = new StringTokenizer(locstr, "$");
while (dollarTokens.hasMoreTokens())
{
String dollarToken = dollarTokens.nextToken().trim();
StringTokenizer colonTokens = new StringTokenizer(dollarToken, ":");
String colonToken = colonTokens.nextToken();
if (colonToken.equals("User"))
{
entity = colonTokens.nextToken().trim();
locator.setUser(JetspeedSecurity.getUser(entity));
}
else if (colonToken.equals("Group"))
{
entity = colonTokens.nextToken().trim();
locator.setGroup(JetspeedSecurity.getGroup(entity));
}
else if (colonToken.equals("Role"))
{
entity = colonTokens.nextToken().trim();
locator.setRole(JetspeedSecurity.getRole(entity));
}
else if (colonToken.equals("Page"))
{
entity = colonTokens.nextToken().trim();
locator.setName(entity);
}
else if (colonToken.equals("MediaType"))
{
entity = colonTokens.nextToken().trim();
locator.setMediaType(entity);
}
else if (colonToken.equals("Country"))
{
entity = colonTokens.nextToken().trim();
locator.setCountry(entity);
}
else if (colonToken.equals("Language"))
{
entity = colonTokens.nextToken().trim();
locator.setLanguage(entity);
}
}
if (logger.isDebugEnabled())
logger.debug("DatabasePsmlManagerService: Returning locator for string: " + locatorToString(locator));
return locator;
}
public PSMLDocument getDocument(String name)
{
// do nothing, deprecated
logger.warn("*** NOT SUPPORTED: GETDOC FROM DATABASE PSML MANAGER!!!");
return null;
}
public boolean saveDocument(String fileOrUrl, PSMLDocument doc)
{
// do nothing, deprecated
logger.warn("*** NOT SUPPORTED: SAVING DOC FROM DATABASE PSML MANAGER!!!");
return false;
}
public boolean saveDocument(PSMLDocument doc)
{
// do nothing, will be deprecated
logger.warn("*** NOT SUPPORTED: SAVING DOC FROM DATABASE PSML MANAGER!!!");
return false;
}
/**
* Returns a PSML document for the given locator
*
* @param locator The locator descriptor(ProfileLocator object) of the
* document to be retrieved.
* @return psmldoc The PSMLDocument object
*/
public PSMLDocument getDocument(ProfileLocator locator)
{
// check the cache for the req'e document if not available in cache
// get the document from database
if (locator == null)
{
String message = "PSMLManager: Must specify a locator";
logger.warn("DatabasePsmlManagerService.getDocument: " + message);
throw new IllegalArgumentException(message);
}
PSMLDocument psmldoc = null;
String locStr = locatorToString(locator);
boolean inCache = false;
if (cachingOn)
{
synchronized (psmlCache)
{
// psmldoc = (PSMLDocument)psmlCache.get(locatorToString(locator));
// if we have seached and found nothing, this is cached as a null value
// so check to see if the key is there
inCache = psmlCache.containsKey(locStr);
if (inCache)
{
psmldoc = (PSMLDocument)psmlCache.get(locStr);
}
}
// if (Log.getLogger().isDebugEnabled())
// Log.info("DatabasePsmlManagerService.getDocument(): psmlcache: " +
// (inCache ? ((psmldoc == null) ? "null present" : "doc present") : "not in cache") + " : " + locStr);
// if in the cache, doc or null, return what's in the cache
if (inCache)
{
return psmldoc;
}
}
try
{
return refresh(locator);
}
catch (Exception e)
{
logger.warn("DatabasePSMLManagerService.getDocument: exception:", e);
throw new RuntimeException("Could not get profile from DB");
}
}
/**
* Stores the PSML document in DB for the given profile
*
* @param profile The profile that holds the PSMLDocument.
* @return PSMLDocument The PSMLDocument that got created in DB.
*/
public PSMLDocument createDocument(Profile profile)
{
return createOrSaveDocument(profile, INSERT);
}
/**
* Update the PSML document in DB for the given profile
*
* @param profile The profile that holds the PSMLDocument.
* @return PSMLDocument The PSMLDocument that got created in DB.
*/
public boolean store(Profile profile)
{
return createOrSaveDocument(profile, UPDATE) != null;
}
private PSMLDocument createOrSaveDocument(Profile profile, int operation)
{
// create record in the database for Portlets for the given
// profile/PSMLDocuemnt,use marsheller to create Portlets
// object and then put it in database, update the cache
if (profile == null)
{
String message = "PSMLManager: Must specify a profile";
logger.warn("DatabasePsmlManagerService.createOrSaveDocument: " + message);
throw new IllegalArgumentException(message);
}
JetspeedUser user = profile.getUser();
Role role = profile.getRole();
Group group = profile.getGroup();
String tableName = null;
Connection dbCon = getDbConnection();
try
{
if (user != null)
{
tableName = "JETSPEED_USER_PROFILE";
if (operation == INSERT)
{
new JetspeedUserProfilePeer().insert(profile, dbCon);
}
else if (operation == UPDATE)
{
new JetspeedUserProfilePeer().update(profile, dbCon);
}
}
else if (role != null)
{
tableName = "JETSPEED_ROLE_PROFILE";
if (operation == INSERT)
{
new JetspeedRoleProfilePeer().insert(profile, dbCon);
}
else if (operation == UPDATE)
{
new JetspeedRoleProfilePeer().update(profile, dbCon);
}
}
else if (group != null)
{
tableName = "JETSPEED_GROUP_PROFILE";
if (operation == INSERT)
{
new JetspeedGroupProfilePeer().insert(profile, dbCon);
}
else if (operation == UPDATE)
{
new JetspeedGroupProfilePeer().update(profile, dbCon);
}
}
if (cachingOn)
{
// insert successful
synchronized (psmlCache)
{
if (logger.isDebugEnabled())
logger.debug("DatabasePsmlManagerService.createOrSaveDocument: caching document: profile: " + locatorToString(profile));
psmlCache.put(locatorToString(profile), profile.getDocument());
}
}
return profile.getDocument();
}
catch (Exception e) // insert failed
{
logger.warn("DatabasePsmlManagerService.createOrSaveDocument: profile: "
+ profile + " tableName: " + tableName, e);
throw new RuntimeException("Could not create new profile in DB");
}
finally
{
// make sure to release the database connection
releaseDbConnection(dbCon);
}
}
/**
* Remove the PSMLDocument/profile for given locator object.
*
* @param locator The profile locator criteria for profile to be removed.
*/
public void removeDocument(ProfileLocator locator)
{
if (locator == null)
{
String message = "PSMLManager: Must specify a locator";
logger.warn("DatabasePsmlManagerService.removeDocument: " + message);
throw new IllegalArgumentException(message);
}
JetspeedUser user = locator.getUser();
Role role = locator.getRole();
Group group = locator.getGroup();
String tableName = null;
// get a database connection
Connection dbCon = getDbConnection();
try
{
if (user != null)
{
new JetspeedUserProfilePeer().delete(locator, dbCon);
tableName = "JETSPEED_USER_PROFILE";
}
else if (role != null)
{
new JetspeedRoleProfilePeer().delete(locator, dbCon);
tableName = "JETSPEED_ROLE_PROFILE";
}
else if (group != null)
{
new JetspeedGroupProfilePeer().delete(locator, dbCon);
tableName = "JETSPEED_GROUP_PROFILE";
}
if (cachingOn)
{
// Delete successful
synchronized (psmlCache)
{
psmlCache.remove(locatorToString(locator));
}
}
}
catch (Exception e) // insert failed
{
logger.warn("DatabasePsmlManagerService.removeDocument: profile: "
+ locatorToString(locator) + " tableName: " + tableName, e);
throw new RuntimeException("Could not delete profile for given locator from DB");
}
finally
{
// make sure to release the database connection
releaseDbConnection(dbCon);
}
}
/**
* Query for a collection of profiles given a profile locator criteria.
* Use SQL engine to get the required profiles.
*
* @param locator The profile locator criteria.
* @return Iterator object with the PSMLDocuments satisfying query
*/
public Iterator query(QueryLocator locator)
{
if (locator == null)
{
String message = "PSMLManager: Must specify a locator";
logger.warn("DatabasePsmlManagerService.query: " + message);
throw new IllegalArgumentException(message);
}
Connection dbCon = getDbConnection();
try
{
List userData = null;
List groupData = null;
List roleData = null;
int queryMode = locator.getQueryMode();
List list = new ArrayList();
switch (queryMode)
{
case QueryLocator.QUERY_USER:
userData = new JetspeedUserProfilePeer().selectOrdered(locator, dbCon);
if (userData != null)
{
list = getProfiles(userData);
}
break;
case QueryLocator.QUERY_GROUP:
groupData = new JetspeedGroupProfilePeer().selectOrdered(locator, dbCon);
if (groupData != null)
{
list = getProfiles(groupData);
}
break;
case QueryLocator.QUERY_ROLE:
roleData = new JetspeedRoleProfilePeer().selectOrdered(locator, dbCon);
if (roleData != null)
{
list = getProfiles(roleData);
}
break;
default: //QUERY_ALL
userData = new JetspeedUserProfilePeer().selectOrdered(locator, dbCon);
if (userData != null)
{
list.addAll(getProfiles(userData));
}
groupData = new JetspeedGroupProfilePeer().selectOrdered(locator, dbCon);
if (groupData != null)
{
list.addAll(getProfiles(groupData));
}
roleData = new JetspeedRoleProfilePeer().selectOrdered(locator, dbCon);
if (roleData != null)
{
list.addAll(getProfiles(roleData));
}
break;
}
return list.iterator();
}
catch (Exception e)
{
logger.warn("DatabasePsmlManagerService.query: exception" , e);
}
finally
{
// make sure to release the databased connection
releaseDbConnection(dbCon);
}
return new ArrayList().iterator(); // return empty non-null iterator
}
/**
* Get profile iterator from given list of objects.
*
* @param data List of JetspeedUserProfile, JetspeedGroupProfile,
* JetspeedRoleProfile, objects
* @return List of profiles
*/
private List getProfiles(List data)
{
List list = new ArrayList();
for (int i = 0; i < data.size(); i++)
{
Object obj = data.get(i);
Portlets portlets = null;
if (obj instanceof JetspeedUserProfile)
{
portlets = DBUtils.bytesToPortlets(((JetspeedUserProfile)obj).getProfile(), this.mapping);
list.add(createUserProfile((JetspeedUserProfile)obj, portlets));
}
else if (obj instanceof JetspeedGroupProfile)
{
portlets = DBUtils.bytesToPortlets(((JetspeedGroupProfile)obj).getProfile(), this.mapping);
list.add(createGroupProfile((JetspeedGroupProfile)obj, portlets));
}
else if (obj instanceof JetspeedRoleProfile)
{
portlets = DBUtils.bytesToPortlets(((JetspeedRoleProfile)obj).getProfile(), this.mapping);
list.add(createRoleProfile((JetspeedRoleProfile)obj, portlets));
}
}
return list;
}
/**
* Get PSMLDocument object for given pagename and portlets.
*
* @param portlets Portlets for the given page name
* @param page page name for this resource
* @return PSMLDocument object for given page and portlets
*/
private PSMLDocument getPSMLDocument(String page, Portlets portlets)
{
PSMLDocument psmldoc = new BasePSMLDocument();
psmldoc.setName(page);
psmldoc.setPortlets(portlets);
return psmldoc;
}
/**
* Given ordered list of locators, find the first document matching
* a profile locator, starting from the beginning of the list and working
* to the end.
*
* @param locator The ordered list of profile locators.
* @return PSMLDocument object for the first document matching a locator
*/
public PSMLDocument getDocument(List locators)
{
if (locators == null)
{
String message = "PSMLManager: Must specify a list of locators";
logger.warn("DatabasePsmlManagerService.getDocument: " + message);
throw new IllegalArgumentException(message);
}
// iterate over the list and invoke getDocument(locator) method
for (int i = 0; i < locators.size(); i++)
{
PSMLDocument psmldoc = getDocument((ProfileLocator)locators.get(i));
if (psmldoc != null)
{
return psmldoc;
}
}
return null;
}
/**
* Returns a PSML document for the given locator, it is called by the cache
* refresher
*
* @param locator The locator descriptor(ProfileLocator object) of the
* document to be retrieved.
* @return psmldoc The PSMLDocument object
*/
public PSMLDocument refresh(ProfileLocator locator)
{
// go to database and get the blob, and marshal the Portlets
if (locator == null)
{
String message = "PSMLManager: Must specify a locator";
logger.warn("DatabasePsmlManagerService.refresh: " + message);
throw new IllegalArgumentException(message);
}
JetspeedUser user = locator.getUser();
Role role = locator.getRole();
Group group = locator.getGroup();
String tableName = null;
List records = null;
Portlets portlets = null;
PSMLDocument psmldoc = null;
String page = null;
Connection dbCon = getDbConnection();
try
{
if (user != null)
{
tableName = "JETSPEED_USER_PROFILE";
records = new JetspeedUserProfilePeer().select(locator, dbCon);
Iterator iterator = records.iterator();
while (iterator.hasNext())
{
JetspeedUserProfile uprofile =
(JetspeedUserProfile)iterator.next();
page = uprofile.getPage();
portlets = DBUtils.bytesToPortlets(uprofile.getProfile(), this.mapping);
}
}
else if (role != null)
{
tableName = "JETSPEED_ROLE_PROFILE";
records = new JetspeedRoleProfilePeer().select(locator, dbCon);
Iterator iterator = records.iterator();
while (iterator.hasNext())
{
JetspeedRoleProfile rprofile =
(JetspeedRoleProfile)iterator.next();
page = rprofile.getPage();
portlets = DBUtils.bytesToPortlets(rprofile.getProfile(), this.mapping);
}
}
else if (group != null)
{
tableName = "JETSPEED_GROUP_PROFILE";
records = new JetspeedGroupProfilePeer().select(locator, dbCon);
Iterator iterator = records.iterator();
while (iterator.hasNext())
{
JetspeedGroupProfile gprofile =
(JetspeedGroupProfile)iterator.next();
page = gprofile.getPage();
portlets = DBUtils.bytesToPortlets(gprofile.getProfile(), this.mapping);
}
}
if (page != null && portlets != null)
{
psmldoc = getPSMLDocument(page, portlets);
if (cachingOn)
{
synchronized (psmlCache)
{
if (logger.isDebugEnabled())
logger.debug("DatabasePsmlManagerService.refresh: caching document: profile: " + locatorToString(locator));
psmlCache.put(locatorToString(locator), psmldoc);
}
}
return psmldoc;
}
else
{
if (cachingOn)
{
// cache the fact that there is NO document matching this profile
psmlCache.put(locatorToString(locator), null);
if (logger.isDebugEnabled())
logger.debug("DatabasePsmlManagerService.refresh: caching 'document not found': profile: " + locatorToString(locator));
}
}
}
catch (Exception e)
{
logger.warn("DatabasePsmlManagerService.refresh: profile: " + locatorToString(locator)
+ " tableName: " + tableName, e);
throw new RuntimeException("Could not refresh profile from DB");
}
finally
{
// make sure to release the database connection
releaseDbConnection(dbCon);
}
if (logger.isDebugEnabled())
logger.debug("DatabasePsmlManagerService.refresh: no document found: profile: "
+ locatorToString(locator));
return null;
}
/** Removes all documents for a given user.
*
* @param user The user object.
*/
public void removeUserDocuments(JetspeedUser user)
{
Connection dbCon = getDbConnection();
try
{
if (user != null)
{
new JetspeedUserProfilePeer().delete(user, dbCon);
}
}
catch (Exception e) // delete failed
{
logger.warn("DatabasePsmlManagerService.removeUserDocuments: exception:", e);
throw new RuntimeException("Could not delete documents for given user from DB");
}
finally
{
// make sure to release the database connection
releaseDbConnection(dbCon);
}
}
/** Removes all documents for a given role.
*
* @param role The role object.
*/
public void removeRoleDocuments(Role role)
{
Connection dbCon = getDbConnection();
try
{
if (role != null)
{
new JetspeedRoleProfilePeer().delete(role, dbCon);
}
}
catch (Exception e) // delete failed
{
logger.warn("DatabasePsmlManagerService.removeRoleDocuments: exception:", e);
throw new RuntimeException("Could not delete documents for given role from DB");
}
finally
{
// make sure to release the database connection
releaseDbConnection(dbCon);
}
}
/** Removes all documents for a given group.
*
* @param group The group object.
*/
public void removeGroupDocuments(Group group)
{
Connection dbCon = getDbConnection();
try
{
if (group != null)
{
new JetspeedGroupProfilePeer().delete(group, dbCon);
}
}
catch (Exception e) // delete failed
{
logger.warn("DatabasePsmlManagerService.removeGroupDocuments: exception:", e);
throw new RuntimeException("Could not delete documents for given group from DB");
}
finally
{
// make sure to release the database connection
releaseDbConnection(dbCon);
}
}
/** Query for a collection of profiles given a profile locator criteria.
* This method should be used when importing or exporting profiles between services.
*
* @param locator The profile locator criteria.
* @return The count of profiles exported.
*/
public int export(PsmlManagerService consumer, QueryLocator locator)
{
Iterator profiles = null;
int count = 0;
try
{
this.consumer = consumer;
profiles = query(locator);
while (profiles.hasNext() )
{
Profile profile = (Profile)profiles.next();
//dumpProfile(profile);
try
{
consumer.createDocument(profile);
count++;
}
catch (Exception ex)
{
try
{
consumer.store(profile);
count++;
}
catch (Exception e)
{
logger.warn("DatabasePsmlManagerService.export: profile: "
+ profile, ex);
}
}
}
}
catch(Exception e)
{
logger.warn("DatabasePsmlManagerService.export: exception:", e);
}
finally
{
}
return count;
}
public Mapping getMapping()
{
return this.mapping;
}
/**
* Creates a user profile from a JetspeedUserProfile database object.
*
* @param entity The user profile entity in the database.
* @param portlets The PSML blob.
* @return A new profile object representing the locator and PSML blob.
*/
public Profile createUserProfile(JetspeedUserProfile entity, Portlets portlets)
{
Profile profile = Profiler.createProfile();
try
{
JetspeedUser user = JetspeedSecurity.getUser(entity.getUserName());
if (null == user)
{
user = JetspeedUserFactory.getInstance();
user.setUserName(entity.getUserName());
}
profile.setUser(user);
profile.setMediaType(entity.getMediaType());
profile.setLanguage(entity.getLanguage());
profile.setCountry(entity.getCountry());
profile.setName(entity.getPage());
profile.setDocument(getPSMLDocument(entity.getPage(), portlets));
}
catch (JetspeedSecurityException e)
{
}
return profile;
}
/**
* Creates a group profile from a JetspeedGroupProfile database object.
*
* @param entity The group profile entity in the database.
* @param portlets The PSML blob.
* @return A new profile object representing the locator and PSML blob.
*/
public Profile createGroupProfile(JetspeedGroupProfile entity, Portlets portlets)
{
Profile profile = Profiler.createProfile();
try
{
Group group = JetspeedSecurity.getGroup(entity.getGroupName());
if (null == group)
{
group = JetspeedGroupFactory.getInstance();
group.setName(entity.getGroupName());
}
profile.setGroup(group);
profile.setMediaType(entity.getMediaType());
profile.setLanguage(entity.getLanguage());
profile.setCountry(entity.getCountry());
profile.setName(entity.getPage());
profile.setDocument(getPSMLDocument(entity.getPage(), portlets));
}
catch (JetspeedSecurityException e)
{
}
return profile;
}
/**
* Creates a role profile from a JetspeedRoleProfile database object.
*
* @param entity The group profile entity in the database.
* @param portlets The PSML blob.
* @return A new profile object representing the locator and PSML blob.
*/
public Profile createRoleProfile(JetspeedRoleProfile entity, Portlets portlets)
{
Profile profile = Profiler.createProfile();
try
{
Role role = JetspeedSecurity.getRole(entity.getRoleName());
if (null == role)
{
role = JetspeedRoleFactory.getInstance();
role.setName(entity.getRoleName());
}
profile.setRole(role);
profile.setMediaType(entity.getMediaType());
profile.setLanguage(entity.getLanguage());
profile.setCountry(entity.getCountry());
profile.setName(entity.getPage());
profile.setDocument(getPSMLDocument(entity.getPage(), portlets));
}
catch (JetspeedSecurityException e)
{
}
return profile;
}
/**
* Get a database connection to the default or specifed torque database pool
*/
private Connection getDbConnection()
{
try
{
// use the default pool if not specified
if (poolName == null)
{
return Torque.getConnection();
}
// otherwise use the specified pool name
else
{
return Torque.getConnection(poolName);
}
}
catch (Exception e)
{
logger.warn("DatabasePsmlManagerService.getDbConnection: exception: " + e);
return null;
}
}
/**
* Release a previously gotten database connection back to the torque pool
*/
private void releaseDbConnection(Connection connection)
{
Torque.closeConnection(connection);
}
}