001/*
002 * (C) Copyright 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.elasticsearch.audit.io;
020
021import static org.nuxeo.common.utils.DateUtils.parseISODateTime;
022import static org.nuxeo.common.utils.DateUtils.toDate;
023import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_CATEGORY;
024import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_COMMENT;
025import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_DOC_LIFE_CYCLE;
026import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_DOC_PATH;
027import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_DOC_TYPE;
028import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_DOC_UUID;
029import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_EVENT_DATE;
030import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_EVENT_ID;
031import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_EXTENDED;
032import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_ID;
033import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_LOG_DATE;
034import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_PRINCIPAL_NAME;
035import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_REPOSITORY_ID;
036
037import java.io.IOException;
038import java.util.HashMap;
039import java.util.Iterator;
040import java.util.Map;
041
042import org.nuxeo.ecm.core.api.impl.blob.AbstractBlob;
043import org.nuxeo.ecm.platform.audit.api.ExtendedInfo;
044import org.nuxeo.ecm.platform.audit.api.LogEntry;
045import org.nuxeo.ecm.platform.audit.impl.ExtendedInfoImpl;
046import org.nuxeo.ecm.platform.audit.impl.LogEntryImpl;
047import org.nuxeo.elasticsearch.audit.io.AuditEntryJSONWriter.BinaryBlobEntrySerializer;
048import org.nuxeo.elasticsearch.audit.io.AuditEntryJSONWriter.MapEntrySerializer;
049
050import com.fasterxml.jackson.core.JsonFactory;
051import com.fasterxml.jackson.core.JsonParser;
052import com.fasterxml.jackson.core.JsonToken;
053import com.fasterxml.jackson.core.Version;
054import com.fasterxml.jackson.databind.JsonNode;
055import com.fasterxml.jackson.databind.ObjectMapper;
056import com.fasterxml.jackson.databind.module.SimpleModule;
057
058public class AuditEntryJSONReader {
059
060    public static LogEntry read(String content) throws IOException {
061
062        ObjectMapper objectMapper = new ObjectMapper();
063        SimpleModule module = new SimpleModule("esAuditJson", Version.unknownVersion());
064        module.addSerializer(Map.class, new MapEntrySerializer());
065        module.addSerializer(AbstractBlob.class, new BinaryBlobEntrySerializer());
066        objectMapper.registerModule(module);
067
068        LogEntryImpl entry = new LogEntryImpl();
069
070        JsonFactory factory = new JsonFactory();
071        factory.setCodec(objectMapper);
072        try (JsonParser jp = factory.createParser(content)) {
073
074            JsonToken tok = jp.nextToken();
075
076            // skip {
077            if (jp.getCurrentToken() == JsonToken.START_OBJECT) {
078                tok = jp.nextToken();
079            }
080
081            while (tok != null && tok != JsonToken.END_OBJECT) {
082                String key = jp.getCurrentName();
083                JsonToken token = jp.nextToken();
084                if (token != JsonToken.VALUE_NULL) {
085                    if (LOG_CATEGORY.equals(key)) {
086                        entry.setCategory(token == JsonToken.VALUE_NULL ? null : jp.getText());
087                    } else if (LOG_PRINCIPAL_NAME.equals(key)) {
088                        entry.setPrincipalName(jp.getText());
089                    } else if (LOG_COMMENT.equals(key)) {
090                        entry.setComment(jp.getText());
091                    } else if (LOG_DOC_LIFE_CYCLE.equals(key)) {
092                        entry.setDocLifeCycle(jp.getText());
093                    } else if (LOG_DOC_PATH.equals(key)) {
094                        entry.setDocPath(jp.getText());
095                    } else if (LOG_DOC_TYPE.equals(key)) {
096                        entry.setDocType(jp.getText());
097                    } else if (LOG_DOC_UUID.equals(key)) {
098                        entry.setDocUUID(jp.getText());
099                    } else if (LOG_EVENT_ID.equals(key)) {
100                        entry.setEventId(jp.getText());
101                    } else if (LOG_REPOSITORY_ID.equals(key)) {
102                        entry.setRepositoryId(jp.getText());
103                    } else if (LOG_ID.equals(key)) {
104                        entry.setId(jp.getLongValue());
105                    } else if (LOG_EVENT_DATE.equals(key)) {
106                        entry.setEventDate(toDate(parseISODateTime(jp.getText())));
107                    } else if (LOG_LOG_DATE.equals(key)) {
108                        entry.setLogDate(toDate(parseISODateTime(jp.getText())));
109                    } else if (LOG_EXTENDED.equals(key)) {
110                        entry.setExtendedInfos(readExtendedInfo(jp, objectMapper));
111                    }
112                }
113                tok = jp.nextToken();
114            }
115        }
116        return entry;
117    }
118
119    public static Map<String, ExtendedInfo> readExtendedInfo(JsonParser jp, ObjectMapper objectMapper)
120            throws IOException {
121
122        Map<String, ExtendedInfo> info = new HashMap<>();
123
124        JsonNode node = jp.readValueAsTree();
125
126        Iterator<String> fieldsIt = node.fieldNames();
127
128        while (fieldsIt.hasNext()) {
129            String fieldName = fieldsIt.next();
130
131            JsonNode field = node.get(fieldName);
132
133            ExtendedInfoImpl ei = null;
134            if (field.isObject() || field.isArray()) {
135                ei = ExtendedInfoImpl.createExtendedInfo(objectMapper.writeValueAsString(field));
136            } else {
137                if (field.isInt() || field.isLong()) {
138                    ei = ExtendedInfoImpl.createExtendedInfo(field.longValue());
139                } else {
140                    ei = ExtendedInfoImpl.createExtendedInfo(field.textValue());
141                }
142            }
143            info.put(fieldName, ei);
144        }
145        return info;
146    }
147
148}