package com.voxeo.moho.util; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.log4j.Logger; import com.voxeo.moho.Participant; public class JoinLockService { private static final Logger LOG = Logger.getLogger(JoinLockService.class); private static JoinLockService INSTANCE = new JoinLockService(); protected final Map<String, LockImpl> _m = new HashMap<String, LockImpl>(); public static JoinLockService getInstance() { return INSTANCE; } public synchronized Lock get(final Participant part, final Participant other) { final List<String> ids1 = new ArrayList<String>(); ids1.add(part.getId()); Participant[] joinees = part.getParticipants(); if (joinees != null && joinees.length > 0) { for (Participant p : joinees) { ids1.add(p.getId()); } } if (other != null) { ids1.add(other.getId()); joinees = other.getParticipants(); if (joinees != null && joinees.length > 0) { for (Participant p : joinees) { ids1.add(p.getId()); } } } final List<String> ids2 = new ArrayList<String>(); ids2.add(part.getId()); if (other != null) { ids2.add(other.getId()); } return get(ids1, ids2); } public synchronized Lock get(final Participant part) { return get(part, null); } protected synchronized Lock get(final List<String> ids1, final List<String> ids2) { Lock retval = null; // find the lock for (final String id : ids1) { if (_m.containsKey(id)) { retval = _m.get(id).getLock(); break; } } // increase the lock counter LockImpl lock; for (final String id : ids2) { lock = _m.get(id); if (lock == null) { if (retval == null) { lock = new LockImpl(); retval = lock.getLock(); } else { lock = new LockImpl(retval); } _m.put(id, lock); if (LOG.isDebugEnabled()) { LOG.debug("Added [" + id + ", " + lock + "]"); } } else { lock.getCounter().incrementAndGet(); if (LOG.isDebugEnabled()) { LOG.debug("Updated [" + id + ", " + lock + "]"); } } } return retval; } public synchronized void remove(final String id) { // find the lock LockImpl lock = _m.get(id); // decrease the lock counter if (lock != null && lock.getCounter().decrementAndGet() < 1) { _m.remove(id); if (LOG.isDebugEnabled()) { LOG.debug("Removed [" + id + ", " + lock + "]"); } } } protected class LockImpl { private final Lock _lock; private final AtomicInteger _counter; public LockImpl() { _lock = new ReentrantLock(); _counter = new AtomicInteger(1); } public LockImpl(final Lock lock) { _lock = lock; _counter = new AtomicInteger(1); } public Lock getLock() { return _lock; } public AtomicInteger getCounter() { return _counter; } @Override public String toString() { return _lock.toString() + "[" + _counter + "]"; } } }