001package org.nuxeo.elasticsearch.audit.io; 002 003import java.io.IOException; 004import java.io.Serializable; 005import java.util.Map; 006 007import org.apache.commons.logging.Log; 008import org.apache.commons.logging.LogFactory; 009import org.codehaus.jackson.JsonGenerationException; 010import org.codehaus.jackson.JsonGenerator; 011import org.codehaus.jackson.map.JsonMappingException; 012import org.codehaus.jackson.map.JsonSerializer; 013import org.codehaus.jackson.map.ObjectMapper; 014import org.codehaus.jackson.map.SerializerProvider; 015import org.codehaus.jackson.map.module.SimpleModule; 016import org.elasticsearch.common.jackson.core.JsonProcessingException; 017import org.joda.time.DateTime; 018import org.joda.time.format.ISODateTimeFormat; 019import org.nuxeo.ecm.core.api.impl.blob.AbstractBlob; 020import org.nuxeo.ecm.platform.audit.api.ExtendedInfo; 021import org.nuxeo.ecm.platform.audit.api.LogEntry; 022 023public class AuditEntryJSONWriter { 024 025 protected static final Log log = LogFactory.getLog(AuditEntryJSONWriter.class); 026 027 public static void asJSON(JsonGenerator jg, LogEntry logEntry) throws IOException { 028 ObjectMapper objectMapper = new ObjectMapper(); 029 SimpleModule module = new SimpleModule("esAuditJson", org.codehaus.jackson.Version.unknownVersion()); 030 module.addSerializer(Map.class, new MapEntrySerializer()); 031 module.addSerializer(AbstractBlob.class, new BinaryBlobEntrySerializer()); 032 objectMapper.registerModule(module); 033 jg.setCodec(objectMapper); 034 035 jg.writeStartObject(); 036 jg.writeStringField("entity-type", "logEntry"); 037 038 writeField(jg, "category", logEntry.getCategory()); 039 writeField(jg, "principalName", logEntry.getPrincipalName()); 040 writeField(jg, "comment", logEntry.getComment()); 041 writeField(jg, "docLifeCycle", logEntry.getDocLifeCycle()); 042 writeField(jg, "docPath", logEntry.getDocPath()); 043 writeField(jg, "docType", logEntry.getDocType()); 044 writeField(jg, "docUUID", logEntry.getDocUUID()); 045 writeField(jg, "eventId", logEntry.getEventId()); 046 writeField(jg, "repositoryId", logEntry.getRepositoryId()); 047 jg.writeStringField("eventDate", ISODateTimeFormat.dateTime().print(new DateTime(logEntry.getEventDate()))); 048 jg.writeNumberField("id", logEntry.getId()); 049 jg.writeStringField("logDate", ISODateTimeFormat.dateTime().print(new DateTime(logEntry.getLogDate()))); 050 Map<String, ExtendedInfo> extended = logEntry.getExtendedInfos(); 051 jg.writeObjectFieldStart("extended"); 052 for (String key : extended.keySet()) { 053 ExtendedInfo ei = extended.get(key); 054 if (ei != null && ei.getSerializableValue() != null) { 055 Serializable value = ei.getSerializableValue(); 056 if (value instanceof String) { 057 String strValue = (String) value; 058 if (isJsonContent(strValue)) { 059 jg.writeFieldName(key); 060 jg.writeRawValue(strValue); 061 } else { 062 jg.writeStringField(key, strValue); 063 } 064 } else { 065 try { 066 jg.writeObjectField(key, ei.getSerializableValue()); 067 } catch (JsonMappingException e) { 068 log.error("No Serializer found.", e); 069 } 070 } 071 } else { 072 jg.writeNullField(key); 073 } 074 } 075 jg.writeEndObject(); 076 077 jg.writeEndObject(); 078 jg.flush(); 079 } 080 081 /** 082 * Helper method used to determine if a String field is actually nested JSON 083 * 084 * @since 7.4 085 */ 086 protected static boolean isJsonContent(String value) { 087 if (value != null) { 088 value = value.trim(); 089 if (value.startsWith("{") && value.endsWith("}")) { 090 return true; 091 } else if (value.startsWith("[") && value.endsWith("]")) { 092 return true; 093 } 094 } 095 return false; 096 } 097 098 protected static void writeField(JsonGenerator jg, String name, String value) throws IOException { 099 if (value == null) { 100 jg.writeNullField(name); 101 } else { 102 jg.writeStringField(name, value); 103 } 104 } 105 106 static class MapEntrySerializer extends JsonSerializer<Map> { 107 108 @Override 109 public void serialize(Map map, JsonGenerator jgen, SerializerProvider provider) throws IOException, 110 JsonProcessingException { 111 jgen.writeStartObject(); 112 for (Object key : map.keySet()) { 113 jgen.writeObjectField((String) key, map.get(key)); 114 } 115 jgen.writeEndObject(); 116 } 117 } 118 119 static class BinaryBlobEntrySerializer extends JsonSerializer<AbstractBlob> { 120 121 @Override 122 public void serialize(AbstractBlob blob, JsonGenerator jgen, SerializerProvider provider) 123 throws JsonGenerationException, IOException { 124 // Do not serizalize 125 jgen.writeNull(); 126 } 127 } 128 129}