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