001/*
002 * (C) Copyright 2006-2014 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 *     Thierry Delprat
016 */
017package org.nuxeo.ecm.platform.audit.service;
018
019import java.io.Serializable;
020import java.util.Date;
021import java.util.List;
022import java.util.Map;
023
024import javax.persistence.EntityManager;
025
026import org.nuxeo.ecm.core.event.Event;
027import org.nuxeo.ecm.core.event.EventBundle;
028import org.nuxeo.ecm.core.persistence.PersistenceProvider;
029import org.nuxeo.ecm.core.persistence.PersistenceProvider.RunCallback;
030import org.nuxeo.ecm.core.persistence.PersistenceProvider.RunVoid;
031import org.nuxeo.ecm.core.persistence.PersistenceProviderFactory;
032import org.nuxeo.ecm.platform.audit.api.ExtendedInfo;
033import org.nuxeo.ecm.platform.audit.api.FilterMapEntry;
034import org.nuxeo.ecm.platform.audit.api.LogEntry;
035import org.nuxeo.ecm.platform.audit.impl.ExtendedInfoImpl;
036import org.nuxeo.runtime.api.Framework;
037
038/**
039 * Contains the Hibernate based (legacy) implementation
040 *
041 * @author tiry
042 */
043public class DefaultAuditBackend extends AbstractAuditBackend implements AuditBackend {
044
045    protected PersistenceProvider persistenceProvider;
046
047    // public for testing purpose !
048    public PersistenceProvider getOrCreatePersistenceProvider() {
049        if (persistenceProvider == null) {
050            activatePersistenceProvider();
051        }
052        return persistenceProvider;
053    }
054
055    protected void activatePersistenceProvider() {
056        Thread thread = Thread.currentThread();
057        ClassLoader last = thread.getContextClassLoader();
058        try {
059            thread.setContextClassLoader(PersistenceProvider.class.getClassLoader());
060            PersistenceProviderFactory persistenceProviderFactory = Framework.getLocalService(PersistenceProviderFactory.class);
061            persistenceProvider = persistenceProviderFactory.newProvider("nxaudit-logs");
062            persistenceProvider.openPersistenceUnit();
063        } finally {
064            thread.setContextClassLoader(last);
065        }
066    }
067
068    protected void deactivatePersistenceProvider() {
069        if (persistenceProvider != null) {
070            persistenceProvider.closePersistenceUnit();
071            persistenceProvider = null;
072        }
073    }
074
075    @Override
076    public void deactivate() {
077        deactivatePersistenceProvider();
078    }
079
080    @Override
081    public void addLogEntries(final List<LogEntry> entries) {
082        getOrCreatePersistenceProvider().run(true, new RunVoid() {
083            @Override
084            public void runWith(EntityManager em) {
085                addLogEntries(em, entries);
086            }
087        });
088    }
089
090    protected void addLogEntries(EntityManager em, List<LogEntry> entries) {
091        LogEntryProvider.createProvider(em).addLogEntries(entries);
092    }
093
094    @Override
095    public List<LogEntry> getLogEntriesFor(final String uuid) {
096        return getOrCreatePersistenceProvider().run(false, new RunCallback<List<LogEntry>>() {
097            @Override
098            public List<LogEntry> runWith(EntityManager em) {
099                return getLogEntriesFor(em, uuid);
100            }
101        });
102    }
103
104    protected List<LogEntry> getLogEntriesFor(EntityManager em, String uuid) {
105        return LogEntryProvider.createProvider(em).getLogEntriesFor(uuid);
106    }
107
108    @Override
109    public List<LogEntry> getLogEntriesFor(final String uuid, final Map<String, FilterMapEntry> filterMap,
110            final boolean doDefaultSort) {
111        return getOrCreatePersistenceProvider().run(false, new RunCallback<List<LogEntry>>() {
112            @Override
113            public List<LogEntry> runWith(EntityManager em) {
114                return getLogEntriesFor(em, uuid, filterMap, doDefaultSort);
115            }
116        });
117    }
118
119    protected List<LogEntry> getLogEntriesFor(EntityManager em, String uuid, Map<String, FilterMapEntry> filterMap,
120            boolean doDefaultSort) {
121        return LogEntryProvider.createProvider(em).getLogEntriesFor(uuid, filterMap, doDefaultSort);
122    }
123
124    @Override
125    public LogEntry getLogEntryByID(final long id) {
126        return getOrCreatePersistenceProvider().run(false, new RunCallback<LogEntry>() {
127            @Override
128            public LogEntry runWith(EntityManager em) {
129                return getLogEntryByID(em, id);
130            }
131        });
132    }
133
134    protected LogEntry getLogEntryByID(EntityManager em, long id) {
135        return LogEntryProvider.createProvider(em).getLogEntryByID(id);
136    }
137
138    @Override
139    public List<LogEntry> nativeQueryLogs(final String whereClause, final int pageNb, final int pageSize) {
140        return getOrCreatePersistenceProvider().run(false, new RunCallback<List<LogEntry>>() {
141            @Override
142            public List<LogEntry> runWith(EntityManager em) {
143                return nativeQueryLogs(em, whereClause, pageNb, pageSize);
144            }
145        });
146    }
147
148    protected List<LogEntry> nativeQueryLogs(EntityManager em, String whereClause, int pageNb, int pageSize) {
149        return LogEntryProvider.createProvider(em).nativeQueryLogs(whereClause, pageNb, pageSize);
150    }
151
152    @Override
153    public List<?> nativeQuery(final String query, final int pageNb, final int pageSize) {
154        return getOrCreatePersistenceProvider().run(false, new RunCallback<List<?>>() {
155            @Override
156            public List<?> runWith(EntityManager em) {
157                return nativeQuery(em, query, pageNb, pageSize);
158            }
159        });
160    }
161
162    protected List<?> nativeQuery(EntityManager em, String query, int pageNb, int pageSize) {
163        return LogEntryProvider.createProvider(em).nativeQuery(query, pageNb, pageSize);
164    }
165
166    @Override
167    public List<?> nativeQuery(final String query, final Map<String, Object> params, final int pageNb,
168            final int pageSize) {
169        return getOrCreatePersistenceProvider().run(false, new RunCallback<List<?>>() {
170            @Override
171            public List<?> runWith(EntityManager em) {
172                return nativeQuery(em, query, params, pageNb, pageSize);
173            }
174        });
175    }
176
177    protected List<?> nativeQuery(EntityManager em, String query, Map<String, Object> params, int pageNb, int pageSize) {
178        return LogEntryProvider.createProvider(em).nativeQuery(query, params, pageNb, pageSize);
179    }
180
181    @Override
182    public List<LogEntry> queryLogs(final String[] eventIds, final String dateRange) {
183        return getOrCreatePersistenceProvider().run(false, new RunCallback<List<LogEntry>>() {
184            @Override
185            public List<LogEntry> runWith(EntityManager em) {
186                return queryLogs(em, eventIds, dateRange);
187            }
188        });
189    }
190
191    protected List<LogEntry> queryLogs(EntityManager em, String[] eventIds, String dateRange) {
192        return LogEntryProvider.createProvider(em).queryLogs(eventIds, dateRange);
193    }
194
195    @Override
196    public List<LogEntry> queryLogsByPage(final String[] eventIds, final String dateRange, final String[] category,
197            final String path, final int pageNb, final int pageSize) {
198        return getOrCreatePersistenceProvider().run(false, new RunCallback<List<LogEntry>>() {
199            @Override
200            public List<LogEntry> runWith(EntityManager em) {
201                return queryLogsByPage(em, eventIds, dateRange, category, path, pageNb, pageSize);
202            }
203        });
204    }
205
206    protected List<LogEntry> queryLogsByPage(EntityManager em, String[] eventIds, String dateRange, String[] category,
207            String path, int pageNb, int pageSize) {
208        return LogEntryProvider.createProvider(em).queryLogsByPage(eventIds, dateRange, category, path, pageNb,
209                pageSize);
210    }
211
212    @Override
213    public List<LogEntry> queryLogsByPage(final String[] eventIds, final Date limit, final String[] category,
214            final String path, final int pageNb, final int pageSize) {
215        return getOrCreatePersistenceProvider().run(false, new RunCallback<List<LogEntry>>() {
216            @Override
217            public List<LogEntry> runWith(EntityManager em) {
218                return queryLogsByPage(em, eventIds, limit, category, path, pageNb, pageSize);
219            }
220        });
221    }
222
223    protected List<LogEntry> queryLogsByPage(EntityManager em, String[] eventIds, Date limit, String[] category,
224            String path, int pageNb, int pageSize) {
225        return LogEntryProvider.createProvider(em).queryLogsByPage(eventIds, limit, category, path, pageNb, pageSize);
226    }
227
228    @Override
229    public long syncLogCreationEntries(final String repoId, final String path, final Boolean recurs) {
230        return getOrCreatePersistenceProvider().run(true, new RunCallback<Long>() {
231            @Override
232            public Long runWith(EntityManager em) {
233                return syncLogCreationEntries(em, repoId, path, recurs);
234            }
235        });
236    }
237
238    protected long syncLogCreationEntries(EntityManager em, String repoId, String path, Boolean recurs) {
239        LogEntryProvider provider = LogEntryProvider.createProvider(em);
240        return syncLogCreationEntries(provider, repoId, path, recurs);
241    }
242
243    public void addLogEntry(final LogEntry entry) {
244        getOrCreatePersistenceProvider().run(true, new RunCallback<Integer>() {
245            @Override
246            public Integer runWith(EntityManager em) {
247                addLogEntry(em, entry);
248                return 0;
249            }
250        });
251    }
252
253    public void addLogEntry(EntityManager em, LogEntry entry) {
254        LogEntryProvider.createProvider(em).addLogEntry(entry);
255    }
256
257    @Override
258    public Long getEventsCount(final String eventId) {
259        return getOrCreatePersistenceProvider().run(false, new RunCallback<Long>() {
260            @Override
261            public Long runWith(EntityManager em) {
262                return getEventsCount(em, eventId);
263            }
264
265        });
266    }
267
268    public Long getEventsCount(EntityManager em, String eventId) {
269        return LogEntryProvider.createProvider(em).countEventsById(eventId);
270    }
271
272    public List<String> getLoggedEventIds() {
273        return getOrCreatePersistenceProvider().run(false, new RunCallback<List<String>>() {
274            @Override
275            public List<String> runWith(EntityManager em) {
276                return getLoggedEventIds(em);
277            }
278
279        });
280    }
281
282    protected List<String> getLoggedEventIds(EntityManager em) {
283        return LogEntryProvider.createProvider(em).findEventIds();
284    }
285
286    @Override
287    public void logEvent(final Event event) {
288        getOrCreatePersistenceProvider().run(true, new RunVoid() {
289            @Override
290            public void runWith(EntityManager em) {
291                logEvent(em, event);
292            }
293        });
294    }
295
296    @Override
297    public void logEvents(final EventBundle eventBundle) {
298        getOrCreatePersistenceProvider().run(true, new RunVoid() {
299            @Override
300            public void runWith(EntityManager em) {
301                logEvents(em, eventBundle);
302            }
303        });
304    }
305
306    protected void logEvents(EntityManager em, EventBundle eventBundle) {
307        boolean processEvents = false;
308        for (String name : getAuditableEventNames()) {
309            if (eventBundle.containsEventName(name)) {
310                processEvents = true;
311                break;
312            }
313        }
314        if (!processEvents) {
315            return;
316        }
317        for (Event event : eventBundle) {
318            logEvent(em, event);
319        }
320    }
321
322    protected void logEvent(EntityManager em, Event event) {
323        LogEntry entry = buildEntryFromEvent(event);
324        if (entry != null) {
325            addLogEntry(em, entry);
326        }
327    }
328
329    // Compat APIs
330
331    protected List<LogEntry> queryLogsByPage(EntityManager em, String[] eventIds, String dateRange, String category,
332            String path, int pageNb, int pageSize) {
333        String[] categories = { category };
334        return queryLogsByPage(em, eventIds, dateRange, categories, path, pageNb, pageSize);
335    }
336
337    protected List<LogEntry> queryLogsByPage(EntityManager em, String[] eventIds, Date limit, String category,
338            String path, int pageNb, int pageSize) {
339        String[] categories = { category };
340        return queryLogsByPage(em, eventIds, limit, categories, path, pageNb, pageSize);
341    }
342
343    @Override
344    public void onApplicationStarted() {
345        // Nothing to do
346    }
347
348    @Override
349    public ExtendedInfo newExtendedInfo(Serializable value) {
350        return ExtendedInfoImpl.createExtendedInfo(value);
351    }
352
353}