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