001/*
002 * (C) Copyright 2006-2011 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 *     bstefanescu
018 */
019package org.nuxeo.ecm.automation.core.operations.services;
020
021import java.io.IOException;
022import java.sql.Date;
023import java.sql.Timestamp;
024import java.util.ArrayList;
025import java.util.LinkedHashMap;
026import java.util.List;
027import java.util.Map;
028
029import javax.persistence.EntityManager;
030import javax.persistence.Query;
031
032import org.nuxeo.ecm.automation.OperationContext;
033import org.nuxeo.ecm.automation.core.Constants;
034import org.nuxeo.ecm.automation.core.annotations.Context;
035import org.nuxeo.ecm.automation.core.annotations.Operation;
036import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
037import org.nuxeo.ecm.automation.core.annotations.Param;
038import org.nuxeo.ecm.core.api.Blob;
039import org.nuxeo.ecm.core.api.Blobs;
040import org.nuxeo.ecm.core.persistence.PersistenceProvider;
041import org.nuxeo.ecm.core.persistence.PersistenceProvider.RunCallback;
042import org.nuxeo.ecm.core.persistence.PersistenceProviderFactory;
043import org.nuxeo.ecm.platform.audit.api.AuditReader;
044import org.nuxeo.ecm.platform.audit.api.LogEntry;
045import org.nuxeo.runtime.api.Framework;
046
047/**
048 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
049 */
050@Operation(id = AuditQuery.ID, category = Constants.CAT_SERVICES, label = "Query Audit Service", description = "Execute a JPA query against the Audit Service. This is returning a blob with the query result. The result is a serialized JSON array. You can use the context to set query variables but you must prefix using 'audit.query.' the context variable keys that match the ones in the query.", addToStudio = false)
051public class AuditQuery {
052
053    public static final String ID = "Audit.Query";
054
055    @Context
056    protected AuditReader audit;
057
058    @Context
059    protected OperationContext ctx;
060
061    @Param(name = "query", required = true, widget = Constants.W_MULTILINE_TEXT)
062    protected String query;
063
064    @Param(name = "pageNo", required = false)
065    protected int pageNo = 1;
066
067    @Param(name = "maxResults", required = false)
068    protected int maxResults;
069
070    @OperationMethod
071    public Blob run() throws IOException {
072        List<LogEntry> result = query();
073        List<Map<String, Object>> rows = new ArrayList<>();
074        for (LogEntry entry : result) {
075            Map<String, Object> obj = new LinkedHashMap<>();
076            obj.put("eventId", entry.getEventId());
077            obj.put("category", entry.getCategory());
078            obj.put("eventDate", entry.getEventDate().getTime());
079            obj.put("principal", entry.getPrincipalName());
080            obj.put("docUUID", entry.getDocUUID());
081            obj.put("docType", entry.getDocType());
082            obj.put("docPath", entry.getDocPath());
083            obj.put("docLifeCycle", entry.getDocLifeCycle());
084            obj.put("repoId", entry.getRepositoryId());
085            obj.put("comment", entry.getComment());
086            // Map<String, ExtendedInfo> info = entry.getExtendedInfos();
087            // if (info != null) {
088            // info.get
089            // }
090            rows.add(obj);
091        }
092        return Blobs.createJSONBlobFromValue(rows);
093    }
094
095    public List<LogEntry> query() {
096        PersistenceProviderFactory pf = Framework.getService(PersistenceProviderFactory.class);
097        PersistenceProvider provider = pf.newProvider("nxaudit-logs");
098        return provider.run(false, new RunCallback<List<LogEntry>>() {
099            @Override
100            @SuppressWarnings("unchecked")
101            public List<LogEntry> runWith(EntityManager em) {
102                Query q = em.createQuery(query);
103                if (maxResults > 0) {
104                    q.setMaxResults(maxResults);
105                    q.setFirstResult((pageNo - 1) * maxResults);
106                }
107                for (Map.Entry<String, Object> entry : ctx.entrySet()) {
108                    String key = entry.getKey();
109                    if (key.startsWith("audit.query.")) {
110                        setQueryParam(q, key.substring("audit.query.".length()), entry.getValue());
111                    }
112                }
113                return q.getResultList();
114            }
115        });
116
117    }
118
119    protected void setQueryParam(Query q, String key, Object value) {
120        if (value instanceof String) {
121            String v = (String) value;
122            if (v.startsWith("{d ") && v.endsWith("}")) {
123                v = v.substring(3, v.length() - 1).trim();
124                int i = v.indexOf(' ');
125                if (i == -1) {
126                    Date date = Date.valueOf(v);
127                    q.setParameter(key, date);
128                } else {
129                    Timestamp ts = Timestamp.valueOf(v);
130                    q.setParameter(key, ts);
131                }
132            } else {
133                q.setParameter(key, v);
134            }
135        } else {
136            q.setParameter(key, value);
137        }
138    }
139}