/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you 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 the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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.apereo.portal.services;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apereo.portal.EntityIdentifier;
import org.apereo.portal.concurrency.IEntityLock;
import org.apereo.portal.concurrency.IEntityLockService;
import org.apereo.portal.concurrency.IEntityLockServiceFactory;
import org.apereo.portal.concurrency.LockingException;
import org.apereo.portal.properties.PropertiesManager;
/**
* This is a bootstrap class and facade for the IEntityLockService implementation. It presents a
* simple api for acquiring lock objects, <code>IEntityLocks</code>, that can be used to control
* concurrent access to portal entities in a multi-server environment. (See
* org.apereo.portal.concurrency.IEntityLockService for a fuller description.)
*
* <p>Currently supported lock types are IEntityLockService.READ_LOCK and
* IEntityLockService.WRITE_LOCK.
*
* <p>If I want to lock an entity for update, I ask the service for a write lock:
*
* <p><code>
* Class type = anEntity.getClass(); // maybe hard-coded(?)<br>
* String key = anEntity.getKey();<br>
* EntityIdentifier ei = new EntityIdentifier(key, type);<br>
* String owner = getThePortalUserId();<br>
* IEntityLock lock = EntityLockService.instance().newWriteLock(ei, owner);<br>
* </code>
*
* <p>Or maybe:
*
* <p><code>
* IEntityLock lock = EntityLockService.instance().newWriteLock(ei, owner, duration);<br>
* </code>
*
* <p>If there are no conflicting locks on the entity, the service returns the requested lock. If I
* acquire the lock, I know that no other client will be able to get a conflicting lock, and from
* then on, I communicate with the service via the lock:
*
* <p><code>
* lock.convert(int newType); // See IEntityLockService for types.<br>
* lock.isValid();<br>
* lock.release();<br>
* lock.renew();<br>
* </code>
*
* <p>A READ lock guarantees shared access; other clients can get READ locks but not WRITE locks. A
* WRITE lock guarantees exclusive access; no other clients can get either READ or WRITE locks on
* the entity.
*
*/
public class EntityLockService {
private static final Log log = LogFactory.getLog(EntityLockService.class);
// Singleton instance of the bootstrap class:
private static EntityLockService instance = null;
// The lock service:
private IEntityLockService lockService = null;
/** Creates new EntityLockService */
private EntityLockService() throws LockingException {
super();
initialize();
}
/** @exception LockingException */
private void initialize() throws LockingException {
String eMsg = null;
String factoryName =
PropertiesManager.getProperty(
"org.apereo.portal.concurrency.IEntityLockServiceFactory", null);
if (factoryName == null) {
log.warn(
"Property org.apereo.portal.concurrency.IEntityLockServiceFactory not configured in PropertiesManager. Defaulting to org.apereo.portal.concurrency.locking.ReferenceEntityLockServiceFactory");
factoryName = "org.apereo.portal.concurrency.locking.ReferenceEntityLockServiceFactory";
}
try {
IEntityLockServiceFactory lockServiceFactory =
(IEntityLockServiceFactory) Class.forName(factoryName).newInstance();
lockService = lockServiceFactory.newLockService();
} catch (Exception e) {
eMsg = "EntityLockService.initialize(): Problem creating entity lock service...";
log.error(eMsg, e);
throw new LockingException(eMsg, e);
}
}
public static synchronized EntityLockService instance() throws LockingException {
if (instance == null) {
instance = new EntityLockService();
}
return instance;
}
/**
* Returns a read lock for the entity type, entity key and owner.
*
* @return org.apereo.portal.concurrency.locking.IEntityLock
* @param entityType Class
* @param entityKey String
* @param owner String
* @exception LockingException
*/
public IEntityLock newReadLock(Class entityType, String entityKey, String owner)
throws LockingException {
return lockService.newLock(entityType, entityKey, IEntityLockService.READ_LOCK, owner);
}
/**
* Returns a read lock for the entity type, entity key and owner.
*
* @return org.apereo.portal.concurrency.locking.IEntityLock
* @param entityType Class
* @param entityKey String
* @param owner String
* @param duration int (in seconds)
* @exception LockingException
*/
public IEntityLock newReadLock(Class entityType, String entityKey, String owner, int duration)
throws LockingException {
return lockService.newLock(
entityType, entityKey, IEntityLockService.READ_LOCK, owner, duration);
}
/**
* Returns a read lock for the <code>IBasicEntity</code> and owner.
*
* @return org.apereo.portal.concurrency.locking.IEntityLock
* @param entityID EntityIdentifier
* @param owner String
* @exception LockingException
*/
public IEntityLock newReadLock(EntityIdentifier entityID, String owner)
throws LockingException {
return lockService.newLock(
entityID.getType(), entityID.getKey(), IEntityLockService.READ_LOCK, owner);
}
/**
* Returns a read lock for the <code>IBasicEntity</code>, owner and duration.
*
* @return org.apereo.portal.concurrency.locking.IEntityLock
* @param entityID EntityIdentifier
* @param owner String
* @param durationSecs int
* @exception LockingException
*/
public IEntityLock newReadLock(EntityIdentifier entityID, String owner, int durationSecs)
throws LockingException {
return lockService.newLock(
entityID.getType(),
entityID.getKey(),
IEntityLockService.READ_LOCK,
owner,
durationSecs);
}
/**
* Returns a write lock for the entity type, entity key and owner.
*
* @return org.apereo.portal.concurrency.locking.IEntityLock
* @param entityType Class
* @param entityKey String
* @param owner String
* @exception LockingException
*/
public IEntityLock newWriteLock(Class entityType, String entityKey, String owner)
throws LockingException {
return lockService.newLock(entityType, entityKey, IEntityLockService.WRITE_LOCK, owner);
}
/**
* Returns a write lock for the entity type, entity key and owner.
*
* @return org.apereo.portal.concurrency.locking.IEntityLock
* @param entityType Class
* @param entityKey String
* @param owner String
* @param durationSecs int
* @exception LockingException
*/
public IEntityLock newWriteLock(
Class entityType, String entityKey, String owner, int durationSecs)
throws LockingException {
return lockService.newLock(
entityType, entityKey, IEntityLockService.WRITE_LOCK, owner, durationSecs);
}
/**
* Returns a write lock for the <code>IBasicEntity</code> and owner.
*
* @return org.apereo.portal.concurrency.locking.IEntityLock
* @param entityID EntityIdentifier
* @param owner String
* @exception LockingException
*/
public IEntityLock newWriteLock(EntityIdentifier entityID, String owner)
throws LockingException {
return lockService.newLock(
entityID.getType(), entityID.getKey(), IEntityLockService.WRITE_LOCK, owner);
}
/**
* Returns a write lock for the <code>IBasicEntity</code>, owner and duration.
*
* @return org.apereo.portal.concurrency.locking.IEntityLock
* @param entityID EntityIdentifier
* @param owner String
* @param durationSecs int
* @exception LockingException
*/
public IEntityLock newWriteLock(EntityIdentifier entityID, String owner, int durationSecs)
throws LockingException {
return lockService.newLock(
entityID.getType(),
entityID.getKey(),
IEntityLockService.WRITE_LOCK,
owner,
durationSecs);
}
}