001/* 002 * (C) Copyright 2015-2017 Nuxeo (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 * Nicolas Chapurlat <nchapurlat@nuxeo.com> 018 */ 019 020package org.nuxeo.ecm.platform.audit.io; 021 022import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 023import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 024import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_CATEGORY; 025import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_COMMENT; 026import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_DOC_LIFE_CYCLE; 027import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_DOC_PATH; 028import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_DOC_TYPE; 029import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_DOC_UUID; 030import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_EVENT_DATE; 031import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_EVENT_ID; 032import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_EXTENDED; 033import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_ID; 034import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_LOG_DATE; 035import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_PRINCIPAL_NAME; 036import static org.nuxeo.ecm.platform.audit.api.BuiltinLogEntryData.LOG_REPOSITORY_ID; 037 038import java.io.IOException; 039import java.io.Serializable; 040import java.util.Date; 041import java.util.Map; 042 043import org.codehaus.jackson.JsonGenerator; 044import org.joda.time.DateTime; 045import org.joda.time.format.DateTimeFormatter; 046import org.joda.time.format.ISODateTimeFormat; 047import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter; 048import org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher; 049import org.nuxeo.ecm.core.io.registry.reflect.Setup; 050import org.nuxeo.ecm.platform.audit.api.ExtendedInfo; 051import org.nuxeo.ecm.platform.audit.api.LogEntry; 052 053/** 054 * Convert {@link LogEntry} to Json. 055 * <p> 056 * This marshaller is enrichable: register class implementing {@link AbstractJsonEnricher} and managing {@link LogEntry} 057 * . 058 * </p> 059 * <p> 060 * This marshaller is also extensible: extend it and simply override 061 * {@link ExtensibleEntityJsonWriter#extend(Object, JsonGenerator)}. 062 * </p> 063 * <p> 064 * Format is: 065 * 066 * <pre> 067 * {@code 068 * { 069 * "entity-type":"logEntry", 070 * "category": "LOG_ENTRY_CATEGORY", 071 * "principalName": "LOG_ENTRY_PRINCIPAL", 072 * "comment": "LOG_ENTRY_COMMENT", 073 * "docLifeCycle": "DOC_LIFECYCLE", 074 * "docPath": "DOC_PATH", 075 * "docType": "DOC_TYPE", 076 * "docUUID": "DOC_UUID", 077 * "eventId": "EVENT_ID", 078 * "repositoryId": "REPO_ID", 079 * "eventDate": "LOG_EVENT_DATE", 080 * "logDate": "LOG_DATE" 081 * <-- contextParameters if there are enrichers activated 082 * <-- additional property provided by extend() method 083 * } 084 * </pre> 085 * 086 * </p> 087 * 088 * @since 7.2 089 */ 090@Setup(mode = SINGLETON, priority = REFERENCE) 091public class LogEntryJsonWriter extends ExtensibleEntityJsonWriter<LogEntry> { 092 093 public static final String ENTITY_TYPE = "logEntry"; 094 095 public LogEntryJsonWriter() { 096 super(ENTITY_TYPE, LogEntry.class); 097 } 098 099 @Override 100 protected void writeEntityBody(LogEntry logEntry, JsonGenerator jg) throws IOException { 101 jg.writeNumberField(LOG_ID, logEntry.getId()); 102 jg.writeStringField(LOG_CATEGORY, logEntry.getCategory()); 103 jg.writeStringField(LOG_PRINCIPAL_NAME, logEntry.getPrincipalName()); 104 jg.writeStringField(LOG_COMMENT, logEntry.getComment()); 105 jg.writeStringField(LOG_DOC_LIFE_CYCLE, logEntry.getDocLifeCycle()); 106 jg.writeStringField(LOG_DOC_PATH, logEntry.getDocPath()); 107 jg.writeStringField(LOG_DOC_TYPE, logEntry.getDocType()); 108 jg.writeStringField(LOG_DOC_UUID, logEntry.getDocUUID()); 109 jg.writeStringField(LOG_EVENT_ID, logEntry.getEventId()); 110 jg.writeStringField(LOG_REPOSITORY_ID, logEntry.getRepositoryId()); 111 DateTimeFormatter dateTime = ISODateTimeFormat.dateTime(); 112 jg.writeStringField(LOG_EVENT_DATE, dateTime.print(new DateTime(logEntry.getEventDate()))); 113 jg.writeStringField(LOG_LOG_DATE, dateTime.print(new DateTime(logEntry.getLogDate()))); 114 writeExtendedInfos(jg, logEntry); 115 } 116 117 protected void writeExtendedInfos(JsonGenerator jg, LogEntry logEntry) throws IOException { 118 Map<String, ExtendedInfo> extended = logEntry.getExtendedInfos(); 119 jg.writeObjectFieldStart(LOG_EXTENDED); 120 for (String key : extended.keySet()) { 121 ExtendedInfo ei = extended.get(key); 122 if (ei != null && ei.getSerializableValue() != null) { 123 writeExtendedInfo(jg, key, ei.getSerializableValue()); 124 } else { 125 jg.writeNullField(key); 126 } 127 } 128 jg.writeEndObject(); 129 } 130 131 protected void writeExtendedInfo(JsonGenerator jg, String key, Serializable value) throws IOException { 132 Class<?> clazz = value.getClass(); 133 if (Long.class.isAssignableFrom(clazz)) { 134 jg.writeNumberField(key, (Long) value); 135 } else if (Integer.class.isAssignableFrom(clazz)) { 136 jg.writeNumberField(key, (Integer) value); 137 } else if (Double.class.isAssignableFrom(clazz)) { 138 jg.writeNumberField(key, (Double) value); 139 } else if (Date.class.isAssignableFrom(clazz)) { 140 jg.writeStringField(key, ISODateTimeFormat.dateTime().print(new DateTime(value))); 141 } else if (String.class.isAssignableFrom(clazz)) { 142 jg.writeStringField(key, (String) value); 143 } else if (Boolean.class.isAssignableFrom(clazz)) { 144 jg.writeBooleanField(key, (Boolean) value); 145 } else { 146 jg.writeStringField(key, value.toString()); 147 } 148 } 149 150}