/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bstefanescu */ package org.eclipse.ecr.automation.core.events; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.ecr.automation.AutomationService; import org.eclipse.ecr.automation.OperationContext; import org.eclipse.ecr.core.event.Event; import org.eclipse.ecr.core.event.EventContext; import org.eclipse.ecr.core.event.impl.DocumentEventContext; /** * TODO: This service should be moved in another project. * * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public class EventHandlerRegistry { private static final Log log = LogFactory.getLog(OperationEventListener.class); protected final AutomationService svc; protected Map<String, List<EventHandler>> handlers; protected Map<String, List<EventHandler>> pchandlers; protected volatile Map<String, List<EventHandler>> lookup; protected volatile Map<String, List<EventHandler>> pclookup; public EventHandlerRegistry(AutomationService svc) { this.svc = svc; handlers = new HashMap<String, List<EventHandler>>(); pchandlers = new HashMap<String, List<EventHandler>>(); } public List<EventHandler> getEventHandlers(String eventId) { return lookup().get(eventId); } public List<EventHandler> getPostCommitEventHandlers(String eventId) { return pclookup().get(eventId); } public void putEventHandler(EventHandler handler) { for (String eventId : handler.getEvents()) { putEventHandler(eventId, handler); } } public synchronized void putEventHandler(String eventId, EventHandler handler) { List<EventHandler> handlers = this.handlers.get(eventId); if (handlers == null) { handlers = new ArrayList<EventHandler>(); this.handlers.put(eventId, handlers); } handlers.add(handler); lookup = null; } public void putPostCommitEventHandler(EventHandler handler) { for (String eventId : handler.getEvents()) { putPostCommitEventHandler(eventId, handler); } } public synchronized void putPostCommitEventHandler(String eventId, EventHandler handler) { List<EventHandler> handlers = this.pchandlers.get(eventId); if (handlers == null) { handlers = new ArrayList<EventHandler>(); this.pchandlers.put(eventId, handlers); } handlers.add(handler); pclookup = null; } public synchronized void removePostCommitEventHandler(EventHandler handler) { for (String eventId : handler.getEvents()) { List<EventHandler> handlers = this.pchandlers.get(eventId); if (handlers != null) { Iterator<EventHandler> it = handlers.iterator(); while (it.hasNext()) { EventHandler h = it.next(); // TODO chainId is not really an unique ID for the event // handler... if (h.chainId.equals(handler.chainId)) { it.remove(); break; } } } } pclookup = null; } public synchronized void removeEventHandler(EventHandler handler) { for (String eventId : handler.getEvents()) { List<EventHandler> handlers = this.handlers.get(eventId); if (handlers != null) { Iterator<EventHandler> it = handlers.iterator(); while (it.hasNext()) { EventHandler h = it.next(); // TODO chainId is not really an unique ID for the event // handler... if (h.chainId.equals(handler.chainId)) { it.remove(); break; } } } } lookup = null; } public synchronized void clear() { handlers = new HashMap<String, List<EventHandler>>(); pchandlers = new HashMap<String, List<EventHandler>>(); lookup = null; pclookup = null; } public Map<String, List<EventHandler>> lookup() { Map<String, List<EventHandler>> _lookup = lookup; if (_lookup == null) { synchronized (this) { if (lookup == null) { lookup = new HashMap<String, List<EventHandler>>(handlers); } _lookup = lookup; } } return _lookup; } public Map<String, List<EventHandler>> pclookup() { Map<String, List<EventHandler>> _lookup = pclookup; if (_lookup == null) { synchronized (this) { if (pclookup == null) { pclookup = new HashMap<String, List<EventHandler>>( pchandlers); } _lookup = pclookup; } } return _lookup; } public Set<String> getPostCommitEventNames() { return pclookup().keySet(); } // TODO: impl remove handlers method? or should refactor runtime to be able // to redeploy only using clear() method public void handleEvent(Event event, List<EventHandler> handlers, boolean saveSession) { if (handlers == null || handlers.isEmpty()) { return; // ignore } EventContext ectx = event.getContext(); OperationContext ctx = null; if (ectx instanceof DocumentEventContext) { ctx = new OperationContext(ectx.getCoreSession()); ctx.setInput(((DocumentEventContext) ectx).getSourceDocument()); } else { // not a document event .. the chain must begin with void // operation - session is not available. ctx = new OperationContext(); } ctx.put("Event", event); ctx.setCommit(saveSession); // avoid reentrant events for (EventHandler handler : handlers) { try { if (handler.isEnabled(ctx, ectx)) { // TODO this will save the // session at each // iteration! svc.run(ctx, handler.getChainId()); } } catch (Exception e) { log.error("Failed to handle event " + event.getName() + " using chain: " + handler.getChainId(), e); } } } }