/* * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. * * Contributors: * bstefanescu */ package org.nuxeo.ecm.automation.core.events; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuxeo.ecm.automation.AutomationService; import org.nuxeo.ecm.automation.OperationContext; import org.nuxeo.ecm.automation.OperationException; import org.nuxeo.ecm.core.api.NuxeoException; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; /** * TODO: This service should be moved in another project, and renamed since it's a service, not a simple registry... * * @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 EventRegistry handlers; protected EventRegistry pchandlers; public EventHandlerRegistry(AutomationService svc) { this.svc = svc; handlers = new EventRegistry(); pchandlers = new EventRegistry(); } public List<EventHandler> getEventHandlers(String eventId) { return handlers.lookup().get(eventId); } public List<EventHandler> getPostCommitEventHandlers(String eventId) { return pchandlers.lookup().get(eventId); } public void putEventHandler(EventHandler handler) { handlers.addContribution(handler); } public synchronized void putPostCommitEventHandler(EventHandler handler) { pchandlers.addContribution(handler); } public synchronized void removePostCommitEventHandler(EventHandler handler) { pchandlers.removeContribution(handler); } public synchronized void removeEventHandler(EventHandler handler) { handlers.removeContribution(handler); } public synchronized void clear() { handlers = new EventRegistry(); pchandlers = new EventRegistry(); } public Set<String> getPostCommitEventNames() { return pchandlers.lookup().keySet(); } public boolean acceptEvent(Event event, List<EventHandler> handlers) { if (handlers == null || handlers.isEmpty()) { return false; } try (OperationContext ctx = open(event)) { EventContext ectx = event.getContext(); ctx.put("Event", event); for (EventHandler handler : handlers) { if (handler.isEnabled(ctx, ectx, true)) { return true; } } return false; } catch (OperationException cause) { throw new NuxeoException(cause); } } protected OperationContext open(Event event) { EventContext ectx = event.getContext(); if (ectx instanceof DocumentEventContext) { OperationContext ctx = new OperationContext(ectx.getCoreSession()); ctx.setInput(((DocumentEventContext) ectx).getSourceDocument()); return ctx; } return new OperationContext(); } // 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(); for (EventHandler handler : handlers) { try (OperationContext ctx = getContext(ectx)) { ctx.put("Event", event); ctx.setCommit(saveSession); // avoid reentrant events if (handler.isEnabled(ctx, ectx, false)) { // TODO this will save the session at each iteration! svc.run(ctx, handler.getChainId()); } } catch (NuxeoException | OperationException e) { log.error("Failed to handle event " + event.getName() + " using chain: " + handler.getChainId(), e); } } } protected OperationContext getContext(EventContext ectx) { if (ectx instanceof DocumentEventContext) { OperationContext ctx = new OperationContext(ectx.getCoreSession()); ctx.setInput(((DocumentEventContext) ectx).getSourceDocument()); return ctx; } // not a document event .. the chain must begin with void // operation - session is not available. return new OperationContext(); } }