/****************************************************************************
* Copyright (C) 2012 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.addon;
import iso.std.iso_iec._24727.tech.schema.ConnectionHandleType;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.openecard.common.enums.EventType;
import org.openecard.common.interfaces.EventCallback;
import org.openecard.common.interfaces.EventManager;
import org.openecard.ws.schema.StatusChange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Johannes Schmölz <johannes.schmoelz@ecsec.de>
* @author Benedikt Biallowons <benedikt.biallowons@ecsec.de>
* @author Dirk Petrautzki <petrautzki@hs-coburg.de>
*/
public class EventHandler implements EventCallback {
private static final Logger logger = LoggerFactory.getLogger(EventHandler.class);
private Map<String, LinkedBlockingQueue<StatusChange>> eventQueues;
private Map<String, ReschedulableTimer> timers;
// after this delay of inactivity an event queue (and it's timer) will be deleted
private static final int deleteDelay = 60 * 1000;
/**
* Create a new EventHandler.
*
* @param eventManager event manager to get events (status changes) from
*/
public EventHandler(EventManager eventManager) {
eventQueues = new HashMap<String, LinkedBlockingQueue<StatusChange>>();
timers = new HashMap<String, ReschedulableTimer>();
eventManager.registerAllEvents(this);
}
/**
*
* @param statusChangeRequest a status change request for a specific session
* @return a StatusChange containing the new status, or null if no eventQueue for the given session exists or if
* interrupted
*/
public StatusChange next(String session) {
//String session = statusChangeRequest.getSessionIdentifier();
StatusChange handle = null;
LinkedBlockingQueue<StatusChange> queue = eventQueues.get(session);
if (queue == null) {
logger.error("No queue found for session {}", session);
return null;
}
do {
try {
timers.get(session).reschedule(deleteDelay);
handle = eventQueues.get(session).poll(30, TimeUnit.SECONDS);
logger.debug("WaitForChange event pulled from event queue.");
} catch (InterruptedException ex) {
return null;
}
} while (handle == null);
return handle;
}
@Override
public void signalEvent(EventType eventType, Object eventData) {
if (eventData instanceof ConnectionHandleType) {
ConnectionHandleType connectionHandle = (ConnectionHandleType) eventData;
for (Map.Entry<String, LinkedBlockingQueue<StatusChange>> entry : eventQueues.entrySet()) {
try {
LinkedBlockingQueue<StatusChange> queue = entry.getValue();
StatusChange statusChange = new StatusChange();
statusChange.setAction(eventType.getEventTypeIdentifier());
statusChange.setConnectionHandle(connectionHandle);
queue.put(statusChange);
} catch (InterruptedException ignore) {
}
}
}
}
/**
* Adds a new EventQueue for a given session.
*
* @param sessionIdentifier session identifier
*/
public void addQueue(final String sessionIdentifier) {
if (eventQueues.get(sessionIdentifier) == null) {
eventQueues.put(sessionIdentifier, new LinkedBlockingQueue<StatusChange>());
ReschedulableTimer timer = new ReschedulableTimer();
timer.schedule(new DeleteTask(sessionIdentifier), deleteDelay);
timers.put(sessionIdentifier, timer);
} else {
timers.get(sessionIdentifier).reschedule(deleteDelay);
}
}
private final class DeleteTask implements Runnable {
private final String sessionIdentifier;
public DeleteTask(String sessionIdentifier) {
this.sessionIdentifier = sessionIdentifier;
}
@Override
public void run() {
eventQueues.remove(sessionIdentifier);
timers.remove(sessionIdentifier);
}
}
}