/* * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Nuxeo - initial API and implementation * */ package org.nuxeo.ecm.platform.audit.api.document; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.api.IdRef; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.platform.audit.api.AuditReader; import org.nuxeo.ecm.platform.audit.api.FilterMapEntry; import org.nuxeo.ecm.platform.audit.api.LogEntry; import org.nuxeo.runtime.api.Framework; /** * Audit log stores event related to the "live" DocumentModel. This means that when retrieving the Audit Log for a * version or a proxy, we must merge part of the "live" document history with the history of the proxy or version. This * helper class fetches the additional parameters that must be used to retrieve history of a version or of a proxy. * * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a> */ public class DocumentAuditHelper { @SuppressWarnings({ "unchecked", "boxing" }) public static AdditionalDocumentAuditParams getAuditParamsForUUID(String uuid, CoreSession session) { IdRef ref = new IdRef(uuid); if (!session.exists(ref)) { return null; } DocumentModel doc = session.getDocument(ref); if (!doc.isProxy() && !doc.isVersion()) { return null; } SourceDocumentResolver resolver = new SourceDocumentResolver(session, doc); resolver.runUnrestricted(); if (resolver.sourceDocument == null) { return null; } String targetUUID = resolver.sourceDocument.getId(); // now get from Audit Logs the creation date of // the version / proxy AuditReader reader = Framework.getLocalService(AuditReader.class); FilterMapEntry filter = new FilterMapEntry(); filter.setColumnName("eventId"); filter.setOperator("="); filter.setQueryParameterName("eventId"); filter.setObject(DocumentEventTypes.DOCUMENT_CREATED); Map<String, FilterMapEntry> filters = new HashMap<String, FilterMapEntry>(); filters.put("eventId", filter); List<LogEntry> entries = reader.getLogEntriesFor(uuid, filters, false); AdditionalDocumentAuditParams result; if (entries != null && entries.size() > 0) { result = new AdditionalDocumentAuditParams(); result.maxDate = entries.get(0).getEventDate(); result.targetUUID = targetUUID; result.eventId = entries.get(0).getId(); } else { // we have no entry in audit log to get the maxDate // fallback to repository timestamp // this code is here only for compatibility so that it works before version events were added to // the audit log if (doc.getPropertyValue("dc:modified") == null) { return null; } result = new AdditionalDocumentAuditParams(); Calendar estimatedDate = ((Calendar) doc.getPropertyValue("dc:modified")); // We can not directly use the repo timestamp because Audit and VCS can be in separated DB // => try to find the matching TS in Audit StringBuilder queryString = new StringBuilder(); queryString.append("from LogEntry log where log.docUUID in ("); queryString.append("'" + targetUUID + "'"); if (doc.isVersion()) { DocumentModelList proxies = session.getProxies(doc.getRef(), null); for (DocumentModel proxy : proxies) { queryString.append(",'" + proxy.getId() + "'"); } } queryString.append(",'" + doc.getId() + "'"); queryString.append(") AND log.eventId IN ("); queryString.append("'" + DocumentEventTypes.DOCUMENT_CREATED + "'"); queryString.append(",'" + DocumentEventTypes.DOCUMENT_CHECKEDIN + "'"); queryString.append(") AND log.eventDate >= :minDate "); queryString.append(" order by log.eventId asc"); estimatedDate.add(Calendar.MILLISECOND, -500); Map<String, Object> params = new HashMap<String, Object>(); params.put("minDate", estimatedDate.getTime()); List<LogEntry> dateEntries = (List<LogEntry>) reader.nativeQuery(queryString.toString(), params, 0, 20); if (dateEntries.size() > 0) { result.targetUUID = targetUUID; Calendar maxDate = new GregorianCalendar(); maxDate.setTime(dateEntries.get(0).getEventDate()); maxDate.add(Calendar.MILLISECOND, -500); result.maxDate = maxDate.getTime(); } else { // no other choice : use the VCS TS // results may be truncated in some DB config result.targetUUID = targetUUID; result.maxDate = ((Calendar) doc.getPropertyValue("dc:modified")).getTime(); } } return result; } }