001/* 002 * (C) Copyright 2006-2016 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.AuditBulkerDescriptor; 038import org.nuxeo.ecm.platform.audit.service.extension.EventDescriptor; 039import org.nuxeo.ecm.platform.audit.service.extension.ExtendedInfoDescriptor; 040import org.nuxeo.runtime.RuntimeServiceEvent; 041import org.nuxeo.runtime.RuntimeServiceListener; 042import org.nuxeo.runtime.api.Framework; 043import org.nuxeo.runtime.model.ComponentContext; 044import org.nuxeo.runtime.model.ComponentInstance; 045import org.nuxeo.runtime.model.ComponentName; 046import org.nuxeo.runtime.model.DefaultComponent; 047 048/** 049 * Event service configuration. 050 * 051 * @author <a href="mailto:ja@nuxeo.com">Julien Anguenot</a> 052 */ 053public class NXAuditEventsService extends DefaultComponent { 054 055 public static final ComponentName NAME = new ComponentName( 056 "org.nuxeo.ecm.platform.audit.service.NXAuditEventsService"); 057 058 private static final String EVENT_EXT_POINT = "event"; 059 060 private static final String EXTENDED_INFO_EXT_POINT = "extendedInfo"; 061 062 private static final String ADAPTER_POINT = "adapter"; 063 064 /** 065 * If passed as true on the event properties, event not logged 066 * 067 * @since 5.7 068 */ 069 public static final String DISABLE_AUDIT_LOGGER = "disableAuditLogger"; 070 071 private static final String BACKEND_EXT_POINT = "backend"; 072 073 protected static final Log log = LogFactory.getLog(NXAuditEventsService.class); 074 075 protected final Set<ExtendedInfoDescriptor> extendedInfoDescriptors = new HashSet<ExtendedInfoDescriptor>(); 076 077 protected final Map<String, List<ExtendedInfoDescriptor>> eventExtendedInfoDescriptors = new HashMap<String, List<ExtendedInfoDescriptor>>(); 078 079 // the adapters that will injected in the EL context for extended 080 // information 081 protected final Set<AdapterDescriptor> documentAdapters = new HashSet<AdapterDescriptor>(); 082 083 protected final Set<String> eventNames = new HashSet<String>(); 084 085 protected AuditBackend backend; 086 087 protected AuditBackendDescriptor backendConfig = new AuditBackendDescriptor(); 088 089 protected AuditBulker bulker; 090 091 protected AuditBulkerDescriptor bulkerConfig = new AuditBulkerDescriptor(); 092 093 @Override 094 public int getApplicationStartedOrder() { 095 return backendConfig.getApplicationStartedOrder(); 096 } 097 098 @Override 099 public void applicationStarted(ComponentContext context) { 100 backend = backendConfig.newInstance(this); 101 backend.onApplicationStarted(); 102 bulker = bulkerConfig.newInstance(backend); 103 bulker.onApplicationStarted(); 104 Framework.addListener(new RuntimeServiceListener() { 105 106 @Override 107 public void handleEvent(RuntimeServiceEvent event) { 108 if (event.id != RuntimeServiceEvent.RUNTIME_STOPPED) { 109 return; 110 } 111 Framework.removeListener(this); 112 try { 113 backend.onShutdown(); 114 } finally { 115 try { 116 bulker.onShutdown(); 117 } finally { 118 bulker = null; 119 } 120 backend = null; 121 } 122 } 123 }); 124 } 125 126 protected void doRegisterAdapter(AdapterDescriptor desc) { 127 if (log.isDebugEnabled()) { 128 log.debug("Registered adapter : " + desc.getName()); 129 } 130 documentAdapters.add(desc); 131 } 132 133 protected void doRegisterEvent(EventDescriptor desc) { 134 String eventName = desc.getName(); 135 boolean eventEnabled = desc.getEnabled(); 136 if (eventEnabled) { 137 eventNames.add(eventName); 138 if (log.isDebugEnabled()) { 139 log.debug("Registered event: " + eventName); 140 } 141 for (ExtendedInfoDescriptor extInfoDesc : desc.getExtendedInfoDescriptors()) { 142 if (extInfoDesc.getEnabled()) { 143 if (eventExtendedInfoDescriptors.containsKey(eventName)) { 144 eventExtendedInfoDescriptors.get(eventName).add(extInfoDesc); 145 } else { 146 List<ExtendedInfoDescriptor> toBeAdded = new ArrayList<ExtendedInfoDescriptor>(); 147 toBeAdded.add(extInfoDesc); 148 eventExtendedInfoDescriptors.put(eventName, toBeAdded); 149 } 150 } else { 151 if (eventExtendedInfoDescriptors.containsKey(eventName)) { 152 eventExtendedInfoDescriptors.get(eventName).remove(extInfoDesc); 153 } 154 } 155 } 156 } else if (eventNames.contains(eventName) && !eventEnabled) { 157 doUnregisterEvent(desc); 158 } 159 } 160 161 protected void doRegisterExtendedInfo(ExtendedInfoDescriptor desc) { 162 if (log.isDebugEnabled()) { 163 log.debug("Registered extended info mapping : " + desc.getKey()); 164 } 165 extendedInfoDescriptors.add(desc); 166 } 167 168 protected void doUnregisterAdapter(AdapterDescriptor desc) { 169 // FIXME: this doesn't look right 170 documentAdapters.remove(desc.getName()); 171 if (log.isDebugEnabled()) { 172 log.debug("Unregistered adapter: " + desc.getName()); 173 } 174 } 175 176 protected void doUnregisterEvent(EventDescriptor desc) { 177 eventNames.remove(desc.getName()); 178 eventExtendedInfoDescriptors.remove(desc.getName()); 179 if (log.isDebugEnabled()) { 180 log.debug("Unregistered event: " + desc.getName()); 181 } 182 } 183 184 protected void doUnregisterExtendedInfo(ExtendedInfoDescriptor desc) { 185 // FIXME: this doesn't look right 186 extendedInfoDescriptors.remove(desc.getKey()); 187 if (log.isDebugEnabled()) { 188 log.debug("Unregistered extended info: " + desc.getKey()); 189 } 190 } 191 192 @Override 193 public <T> T getAdapter(Class<T> adapter) { 194 if (adapter.getCanonicalName().equals(DocumentHistoryReader.class.getCanonicalName())) { 195 return adapter.cast(new DocumentHistoryReaderImpl()); 196 } else { 197 if (backend != null) { 198 return adapter.cast(backend); 199 } else { 200 log.error("Can not provide service " + adapter.getCanonicalName() + " since backend is undefined"); 201 return null; 202 } 203 } 204 } 205 206 public Set<String> getAuditableEventNames() { 207 return eventNames; 208 } 209 210 public AuditBackend getBackend() { 211 return backend; 212 } 213 214 public Set<AdapterDescriptor> getDocumentAdapters() { 215 return documentAdapters; 216 } 217 218 /** 219 * @since 7.4 220 */ 221 public Map<String, List<ExtendedInfoDescriptor>> getEventExtendedInfoDescriptors() { 222 return eventExtendedInfoDescriptors; 223 } 224 225 public Set<ExtendedInfoDescriptor> getExtendedInfoDescriptors() { 226 return extendedInfoDescriptors; 227 } 228 229 @Override 230 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 231 if (extensionPoint.equals(EVENT_EXT_POINT)) { 232 doRegisterEvent((EventDescriptor) contribution); 233 } else if (extensionPoint.equals(EXTENDED_INFO_EXT_POINT)) { 234 doRegisterExtendedInfo((ExtendedInfoDescriptor) contribution); 235 } else if (extensionPoint.equals(ADAPTER_POINT)) { 236 doRegisterAdapter((AdapterDescriptor) contribution); 237 } else if (contribution instanceof AuditBackendDescriptor) { 238 backendConfig = (AuditBackendDescriptor)contribution; 239 } else if (contribution instanceof AuditBulkerDescriptor) { 240 bulkerConfig = (AuditBulkerDescriptor)contribution; 241 } 242 } 243 244 @Override 245 public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 246 if (extensionPoint.equals(EVENT_EXT_POINT)) { 247 doUnregisterEvent((EventDescriptor) contribution); 248 } else if (extensionPoint.equals(EXTENDED_INFO_EXT_POINT)) { 249 doUnregisterExtendedInfo((ExtendedInfoDescriptor) contribution); 250 } else if (extensionPoint.equals(ADAPTER_POINT)) { 251 doUnregisterAdapter((AdapterDescriptor) contribution); 252 } 253 } 254 255}