001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.platform.audit.service;
021
022import java.util.ArrayList;
023import java.util.HashMap;
024import java.util.HashSet;
025import java.util.List;
026import java.util.Map;
027import java.util.Set;
028
029import org.apache.commons.logging.Log;
030import org.apache.commons.logging.LogFactory;
031import org.nuxeo.ecm.platform.audit.api.DocumentHistoryReader;
032import org.nuxeo.ecm.platform.audit.api.document.DocumentHistoryReaderImpl;
033import org.nuxeo.ecm.platform.audit.service.extension.AdapterDescriptor;
034import org.nuxeo.ecm.platform.audit.service.extension.AuditBackendDescriptor;
035import org.nuxeo.ecm.platform.audit.service.extension.EventDescriptor;
036import org.nuxeo.ecm.platform.audit.service.extension.ExtendedInfoDescriptor;
037import org.nuxeo.runtime.model.ComponentContext;
038import org.nuxeo.runtime.model.ComponentInstance;
039import org.nuxeo.runtime.model.ComponentName;
040import org.nuxeo.runtime.model.DefaultComponent;
041
042/**
043 * Event service configuration.
044 *
045 * @author <a href="mailto:ja@nuxeo.com">Julien Anguenot</a>
046 */
047public class NXAuditEventsService extends DefaultComponent {
048
049    public static final ComponentName NAME = new ComponentName(
050            "org.nuxeo.ecm.platform.audit.service.NXAuditEventsService");
051
052    private static final String EVENT_EXT_POINT = "event";
053
054    private static final String EXTENDED_INFO_EXT_POINT = "extendedInfo";
055
056    private static final String ADAPTER_POINT = "adapter";
057
058    /**
059     * If passed as true on the event properties, event not logged
060     *
061     * @since 5.7
062     */
063    public static final String DISABLE_AUDIT_LOGGER = "disableAuditLogger";
064
065    private static final String BACKEND_EXT_POINT = "backend";
066
067    protected static final Log log = LogFactory.getLog(NXAuditEventsService.class);
068
069    protected final Set<ExtendedInfoDescriptor> extendedInfoDescriptors = new HashSet<ExtendedInfoDescriptor>();
070
071    protected final Map<String, List<ExtendedInfoDescriptor>> eventExtendedInfoDescriptors = new HashMap<String, List<ExtendedInfoDescriptor>>();
072
073    // the adapters that will injected in the EL context for extended
074    // information
075    protected final Set<AdapterDescriptor> documentAdapters = new HashSet<AdapterDescriptor>();
076
077    protected final Set<String> eventNames = new HashSet<String>();
078
079    protected AuditBackend backend;
080
081    @Override
082    public void applicationStarted(ComponentContext context) {
083        if (backend != null) {
084            backend.onApplicationStarted();
085        }
086    }
087
088    @Override
089    public void deactivate(ComponentContext context) {
090        backend.deactivate();
091        super.deactivate(context);
092    }
093
094    protected void doRegisterAdapter(AdapterDescriptor desc) {
095        if (log.isDebugEnabled()) {
096            log.debug("Registered adapter : " + desc.getName());
097        }
098        documentAdapters.add(desc);
099    }
100
101    protected void doRegisterBackend(AuditBackendDescriptor desc) {
102        if (backend != null) {
103            backend.deactivate();
104        }
105        backend = desc.newInstance();
106        backend.activate(this);
107    }
108
109    protected void doRegisterEvent(EventDescriptor desc) {
110        String eventName = desc.getName();
111        boolean eventEnabled = desc.getEnabled();
112        if (eventEnabled) {
113            eventNames.add(eventName);
114            if (log.isDebugEnabled()) {
115                log.debug("Registered event: " + eventName);
116            }
117            for (ExtendedInfoDescriptor extInfoDesc : desc.getExtendedInfoDescriptors()) {
118                if (extInfoDesc.getEnabled()) {
119                    if (eventExtendedInfoDescriptors.containsKey(eventName)) {
120                        eventExtendedInfoDescriptors.get(eventName).add(extInfoDesc);
121                    } else {
122                        List<ExtendedInfoDescriptor> toBeAdded = new ArrayList<ExtendedInfoDescriptor>();
123                        toBeAdded.add(extInfoDesc);
124                        eventExtendedInfoDescriptors.put(eventName, toBeAdded);
125                    }
126                } else {
127                    if (eventExtendedInfoDescriptors.containsKey(eventName)) {
128                        eventExtendedInfoDescriptors.get(eventName).remove(extInfoDesc);
129                    }
130                }
131            }
132        } else if (eventNames.contains(eventName) && !eventEnabled) {
133            doUnregisterEvent(desc);
134        }
135    }
136
137    protected void doRegisterExtendedInfo(ExtendedInfoDescriptor desc) {
138        if (log.isDebugEnabled()) {
139            log.debug("Registered extended info mapping : " + desc.getKey());
140        }
141        extendedInfoDescriptors.add(desc);
142    }
143
144    protected void doUnregisterAdapter(AdapterDescriptor desc) {
145        // FIXME: this doesn't look right
146        documentAdapters.remove(desc.getName());
147        if (log.isDebugEnabled()) {
148            log.debug("Unregistered adapter: " + desc.getName());
149        }
150    }
151
152    protected void doUnregisterEvent(EventDescriptor desc) {
153        eventNames.remove(desc.getName());
154        eventExtendedInfoDescriptors.remove(desc.getName());
155        if (log.isDebugEnabled()) {
156            log.debug("Unregistered event: " + desc.getName());
157        }
158    }
159
160    protected void doUnregisterExtendedInfo(ExtendedInfoDescriptor desc) {
161        // FIXME: this doesn't look right
162        extendedInfoDescriptors.remove(desc.getKey());
163        if (log.isDebugEnabled()) {
164            log.debug("Unregistered extended info: " + desc.getKey());
165        }
166    }
167
168    @Override
169    public <T> T getAdapter(Class<T> adapter) {
170        if (adapter.getCanonicalName().equals(DocumentHistoryReader.class.getCanonicalName())) {
171            return adapter.cast(new DocumentHistoryReaderImpl());
172        } else {
173            if (backend != null) {
174                return adapter.cast(backend);
175            } else {
176                log.error("Can not provide service " + adapter.getCanonicalName() + " since backend is undefined");
177                return null;
178            }
179        }
180    }
181
182    public Set<String> getAuditableEventNames() {
183        return eventNames;
184    }
185
186    public AuditBackend getBackend() {
187        return backend;
188    }
189
190    public Set<AdapterDescriptor> getDocumentAdapters() {
191        return documentAdapters;
192    }
193
194    /**
195     * @since 7.4
196     */
197    public Map<String, List<ExtendedInfoDescriptor>> getEventExtendedInfoDescriptors() {
198        return eventExtendedInfoDescriptors;
199    }
200
201    public Set<ExtendedInfoDescriptor> getExtendedInfoDescriptors() {
202        return extendedInfoDescriptors;
203    }
204
205    @Override
206    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
207        if (extensionPoint.equals(EVENT_EXT_POINT)) {
208            doRegisterEvent((EventDescriptor) contribution);
209        } else if (extensionPoint.equals(EXTENDED_INFO_EXT_POINT)) {
210            doRegisterExtendedInfo((ExtendedInfoDescriptor) contribution);
211        } else if (extensionPoint.equals(ADAPTER_POINT)) {
212            doRegisterAdapter((AdapterDescriptor) contribution);
213        } else if (extensionPoint.equals(BACKEND_EXT_POINT)) {
214            doRegisterBackend((AuditBackendDescriptor) contribution);
215        }
216    }
217
218    @Override
219    public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
220        if (extensionPoint.equals(EVENT_EXT_POINT)) {
221            doUnregisterEvent((EventDescriptor) contribution);
222        } else if (extensionPoint.equals(EXTENDED_INFO_EXT_POINT)) {
223            doUnregisterExtendedInfo((ExtendedInfoDescriptor) contribution);
224        } else if (extensionPoint.equals(ADAPTER_POINT)) {
225            doUnregisterAdapter((AdapterDescriptor) contribution);
226        }
227    }
228
229}