package org.piraso.server.service;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.piraso.api.PirasoLogger;
import org.piraso.api.Preferences;
import org.piraso.server.PirasoEntryPoint;
import org.piraso.server.PirasoRequest;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DefaultUserRegistryImpl implements UserRegistry {
private static final Log LOG = PirasoLogger.getUserRegistry();
/**
* lock instance
*/
private final Lock lock = new ReentrantLock();
/**
* Contains the map of {@link User} and {@link ResponseLoggerService}.
*/
private Map<User, ResponseLoggerService> userLoggerMap = Collections.synchronizedMap(new LinkedHashMap<User, ResponseLoggerService>(20));
/**
* Retrieve all {@link org.piraso.api.Preferences} given the monitored address.
*
* @param entryPoint the http servlet request
* @return list of {@link org.piraso.api.Preferences}
* @throws java.io.IOException on io error
*/
public List<Preferences> getContextPreferences(PirasoEntryPoint entryPoint) throws IOException {
List<Preferences> list = new LinkedList<Preferences>();
List<ResponseLoggerService> tmp = new ArrayList<ResponseLoggerService>(userLoggerMap.values());
for(ResponseLoggerService rl : tmp) {
Preferences preferences = rl.getPreferences();
if(rl.isAlive() && rl.isWatched(getMonitoredAddr(entryPoint)) &&
preferences.isUrlAcceptable(entryPoint.getPath())) {
list.add(preferences);
}
}
return list;
}
public Map<User, ResponseLoggerService> getUserLoggerMap() {
return new HashMap<User, ResponseLoggerService>(userLoggerMap);
}
/**
* Retrieve all {@link ResponseLoggerService} given the monitored address.
*
* @param request the http servlet request
* @return list of {@link ResponseLoggerService}
* @throws IOException on io error
*/
public List<ResponseLoggerService> getContextLoggers(PirasoEntryPoint request) throws IOException {
List<ResponseLoggerService> list = new LinkedList<ResponseLoggerService>();
List<ResponseLoggerService> tmp = new ArrayList<ResponseLoggerService>(userLoggerMap.values());
for(ResponseLoggerService rl : tmp) {
Preferences preferences = rl.getPreferences();
if(rl.isAlive() && rl.isWatched(getMonitoredAddr(request)) &&
preferences.isUrlAcceptable(request.getPath())) {
list.add(rl);
}
}
return list;
}
public void clear() {
userLoggerMap.clear();
}
private String getMonitoredAddr(PirasoEntryPoint request) {
return request.getRemoteAddr();
}
public boolean isWatched(PirasoEntryPoint request) throws IOException {
return CollectionUtils.isNotEmpty(getContextLoggers(request));
}
public boolean isUserExist(User user) {
lock.lock();
try {
return userLoggerMap.containsKey(user);
} finally {
lock.unlock();
}
}
public User createOrGetUser(PirasoRequest request) {
return new User(request);
}
public ResponseLoggerService getLogger(User user) {
return userLoggerMap.get(user);
}
private ResponseLoggerService stopServiceIfExist(User user) throws IOException {
if(isUserExist(user)) {
ResponseLoggerService logger = userLoggerMap.get(user);
if(logger.isAlive()) {
logger.stop();
}
return logger;
}
return null;
}
/**
* Associate user with a {@link ResponseLoggerService}.
*
* @param user the user
* @param service the response logger service
* @throws java.io.IOException on io error
*/
public void associate(User user, ResponseLoggerService service) throws IOException {
lock.lock();
try {
if(LOG.isInfoEnabled() && user != null) {
LOG.info(String.format(
"[PIRASO USER]: User ASSOCIATED with address '%s' and activity id '%s'.",
user.getRemoteAddr(),
user.getActivityUuid())
);
}
stopServiceIfExist(user);
service.addStopListener(new StoppedLoggerHandler());
userLoggerMap.put(user, service);
} finally {
lock.unlock();
}
}
public void removeUser(User user) throws IOException {
lock.lock();
try {
if(isUserExist(user)) {
if(LOG.isInfoEnabled() && user != null) {
LOG.info(String.format(
"[PIRASO USER]: User REMOVED with address '%s' and activity id '%s'.",
user.getRemoteAddr(),
user.getActivityUuid())
);
}
stopServiceIfExist(user);
userLoggerMap.remove(user);
}
} finally {
lock.unlock();
}
}
private class StoppedLoggerHandler implements StopLoggerListener {
public void stopped(StopLoggerEvent evt) {
lock.lock();
try {
ResponseLoggerService service = (ResponseLoggerService) evt.getSource();
removeUser(service.getUser());
} catch (IOException e) {
LOG.warn(e.getMessage(), e);
} finally {
lock.unlock();
}
}
}
}