AuditLogTimelineEventProvider.java 9.14 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.timeline.TimelineEvent
 *  com.adobe.granite.timeline.TimelineEventProvider
 *  com.adobe.granite.timeline.TimelineEventType
 *  com.day.cq.audit.AuditLog
 *  com.day.cq.audit.AuditLogEntry
 *  com.day.cq.wcm.api.AuditLogTimelineEventType
 *  com.day.cq.wcm.api.PageModification
 *  com.day.cq.wcm.api.PageModification$ModificationType
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.resource.Resource
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.wcm.core.impl;

import com.adobe.granite.timeline.TimelineEvent;
import com.adobe.granite.timeline.TimelineEventProvider;
import com.adobe.granite.timeline.TimelineEventType;
import com.day.cq.audit.AuditLog;
import com.day.cq.audit.AuditLogEntry;
import com.day.cq.wcm.api.AuditLogTimelineEventType;
import com.day.cq.wcm.api.PageModification;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
@Service
public class AuditLogTimelineEventProvider
implements TimelineEventProvider {
    public static final TimelineEventType EVENT_TYPE = new AuditLogTimelineEventType(){

        public String getName() {
            return AuditLogTimelineEventType.class.getCanonicalName();
        }
    };
    private static final String[] AUDIT_TOPICS = new String[]{"com/day/cq/wcm/core/page", "com/day/cq/replication"};
    private static final DateFormat FORMAT_DATE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private final Logger log = LoggerFactory.getLogger(AuditLogTimelineEventProvider.class);
    @Reference
    private AuditLog auditLog;

    public boolean accepts(Resource resource) {
        return null != resource;
    }

    public Collection<TimelineEvent> getEvents(Resource resource) {
        ArrayList<TimelineEvent> events = new ArrayList<TimelineEvent>();
        FilteredModificationsBucket modBucket = new FilteredModificationsBucket(resource);
        AuditLogEntry[] logEntries = this.auditLog.getLatestEvents(AUDIT_TOPICS, resource.getPath(), -1);
        this.log.debug("got [{}] audit log entries for resource [{}]", (Object)logEntries.length, (Object)resource.getPath());
        boolean ignoreCreate = false;
        block5 : for (AuditLogEntry logEntry : logEntries) {
            String category = logEntry.getCategory();
            if (category.equals("com/day/cq/wcm/core/page")) {
                PageModification.ModificationType modificationType = PageModification.ModificationType.fromName((String)logEntry.getType());
                switch (modificationType) {
                    case MODIFIED: {
                        this.log.debug("adding page modification audit log entry [{}] to bucket for [{}]: " + FORMAT_DATE.format(logEntry.getTime()), (Object)logEntry.getPath(), (Object)resource.getPath());
                        modBucket.add(logEntry, modificationType);
                        continue block5;
                    }
                    case CREATED: {
                        if (!ignoreCreate) {
                            this.log.debug("adding page creation audit log entry [{}] for [{}]", (Object)logEntry.getPath(), (Object)resource.getPath());
                            events.add(new AuditLogTimelineEvent(logEntry, resource));
                        } else {
                            this.log.debug("skipping page creation audit log entry [{}] for [{}]", (Object)logEntry.getPath(), (Object)resource.getPath());
                        }
                        ignoreCreate = true;
                        continue block5;
                    }
                    case VERSION_CREATED: {
                        this.log.debug("ignoring page versioning audit log entry [{}] for [{}]", (Object)logEntry.getPath(), (Object)resource.getPath());
                        modBucket.add(logEntry, modificationType);
                        continue block5;
                    }
                }
                this.log.debug("adding audit log entry [{}] for [{}]", (Object)logEntry.getType(), (Object)resource.getPath());
                events.add(new AuditLogTimelineEvent(logEntry, resource));
                continue;
            }
            if (category.equals("com/day/cq/replication")) {
                this.log.debug("added replication audit log entry [{}] as timeline event for [{}]", (Object)logEntry.getPath(), (Object)resource.getPath());
                events.add(new AuditLogTimelineEvent(logEntry, resource));
                continue;
            }
            this.log.debug("ignoring unknown audit log event category [{}] on [{}]", (Object)category, (Object)resource.getPath());
        }
        Collection<TimelineEvent> bucketEvents = modBucket.getTimelineEvents();
        this.log.debug("adding [{}] page modifications event from bucket for [{}]", (Object)bucketEvents.size(), (Object)resource.getPath());
        events.addAll(bucketEvents);
        this.log.debug("returning a total of [{}] timeline events for [{}]", (Object)events.size(), (Object)resource.getPath());
        if (this.log.isDebugEnabled()) {
            for (TimelineEvent event : events) {
                Calendar cal = Calendar.getInstance();
                cal.setTimeInMillis(event.getTime());
                this.log.debug("    >> [" + FORMAT_DATE.format(cal.getTime()) + " :: " + event.getUserID() + "] {} : {} - [" + event.getOrigin() + "]", (Object)event.getType(), (Object)event.getAction());
            }
        }
        return events;
    }

    public TimelineEventType getType() {
        return EVENT_TYPE;
    }

    protected void bindAuditLog(AuditLog auditLog) {
        this.auditLog = auditLog;
    }

    protected void unbindAuditLog(AuditLog auditLog) {
        if (this.auditLog == auditLog) {
            this.auditLog = null;
        }
    }

    private static class FilteredModificationsBucket {
        final Map<Long, ArrayList<AuditLogEntry>> daysMap = new HashMap<Long, ArrayList<AuditLogEntry>>();
        private final Resource resource;
        private String lastUserId;
        private boolean versionCreated;

        public FilteredModificationsBucket(Resource resource) {
            this.resource = resource;
        }

        public void add(AuditLogEntry newEntry, PageModification.ModificationType modificationType) {
            if (PageModification.ModificationType.VERSION_CREATED == modificationType) {
                this.versionCreated = true;
            } else {
                String userId = newEntry.getUserId();
                Calendar cal = Calendar.getInstance();
                cal.setTime(newEntry.getTime());
                cal.set(11, 0);
                cal.set(12, 0);
                cal.set(13, 0);
                cal.set(14, 0);
                ArrayList entriesByDay = this.daysMap.get(cal.getTimeInMillis());
                if (null == entriesByDay) {
                    entriesByDay = new ArrayList();
                }
                if (!userId.equals(this.lastUserId) || this.versionCreated) {
                    entriesByDay.add(newEntry);
                    this.lastUserId = newEntry.getUserId();
                    this.versionCreated = false;
                }
                this.daysMap.put(cal.getTimeInMillis(), entriesByDay);
            }
        }

        public Collection<TimelineEvent> getTimelineEvents() {
            ArrayList<TimelineEvent> events = new ArrayList<TimelineEvent>();
            for (List entriesByDay : this.daysMap.values()) {
                for (AuditLogEntry entry : entriesByDay) {
                    events.add(new AuditLogTimelineEvent(entry, this.resource));
                }
            }
            return events;
        }
    }

    private static class AuditLogTimelineEvent
    implements TimelineEvent {
        private final AuditLogEntry logEntry;
        private final Resource resource;

        public AuditLogTimelineEvent(AuditLogEntry logEntry, Resource resource) {
            this.logEntry = logEntry;
            this.resource = resource;
        }

        public String getAction() {
            return this.logEntry.getCategory().equals("com/day/cq/wcm/core/page") ? PageModification.ModificationType.fromName((String)this.logEntry.getType()).toString() : this.logEntry.getType();
        }

        public String getDescription() {
            return null;
        }

        public String getOrigin() {
            return this.resource.getPath();
        }

        public long getTime() {
            return this.logEntry.getTime().getTime();
        }

        public TimelineEventType getType() {
            return AuditLogTimelineEventProvider.EVENT_TYPE;
        }

        public String getUserID() {
            return this.logEntry.getUserId();
        }
    }

}