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