/* * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * * * $Id: $ */ package org.nuxeo.ecm.platform.audit.io; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentFactory; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import org.nuxeo.ecm.core.api.DocumentRef; import org.nuxeo.ecm.core.api.NuxeoException; import org.nuxeo.ecm.platform.audit.api.AuditLogger; import org.nuxeo.ecm.platform.audit.api.LogEntry; import org.nuxeo.runtime.api.Framework; /** * Audit log entry importer/exporter. * <p> * Could be overridden to externalize additional information of a redefined LogEntry. * * @author DM */ // FIXME: design issue - this is a utility class (only static methods) with no subclasses (misleading name). public class IOLogEntryBase { private static final Log log = LogFactory.getLog(IOLogEntryBase.class); public static final String DOCUMENT_TAG = "documentLogs"; public static final String LOGENTRY_TAG = "logEntry"; public static void write(List<LogEntry> logEntries, OutputStream out) throws IOException { Document jdoc = writeDocument(logEntries); writeXML(jdoc, out); } private static Document writeDocument(List<LogEntry> logEntries) { Document document = DocumentFactory.getInstance().createDocument(); document.setName("logEntries"); Element rootElement = document.addElement(DOCUMENT_TAG); for (LogEntry logEntry : logEntries) { Element logEntryElement = rootElement.addElement(LOGENTRY_TAG); writeLogEntry(logEntryElement, logEntry); } return document; } /** * Could be overridden to put other (additional) data. */ protected static void writeLogEntry(Element logEntryElement, LogEntry logEntry) { logEntryElement.addAttribute("category", logEntry.getCategory()); logEntryElement.addAttribute("comment", logEntry.getComment()); logEntryElement.addAttribute("docLifeCycle", logEntry.getDocLifeCycle()); logEntryElement.addAttribute("docPath", logEntry.getDocPath()); logEntryElement.addAttribute("docType", logEntry.getDocType()); logEntryElement.addAttribute("docUUID", logEntry.getDocUUID()); logEntryElement.addAttribute("repoId", logEntry.getRepositoryId()); String creationDate = getDateFormat().format(logEntry.getEventDate()); logEntryElement.addAttribute("creationDate", creationDate); logEntryElement.addAttribute("eventId", logEntry.getEventId()); logEntryElement.addAttribute("principalName", logEntry.getPrincipalName()); } public static List<LogEntry> read(InputStream in) throws IOException { Document jDoc = loadXML(in); return readDocument(jDoc); } /** * Will translate from a jdoc to a list of LogEntry objects. */ @SuppressWarnings({ "unchecked" }) protected static List<LogEntry> readDocument(Document doc) { List<LogEntry> logEntries = new ArrayList<LogEntry>(); AuditLogger audit = Framework.getLocalService(AuditLogger.class); Element rootElement = doc.getRootElement(); Iterator<Element> it = rootElement.elementIterator(); while (it.hasNext()) { Element logEntryElement = it.next(); LogEntry logEntry = readLogEntry(audit, logEntryElement); logEntries.add(logEntry); } return logEntries; } /** * Could be overridden to get other (additional) data. * * @param logEntryElement */ protected static LogEntry readLogEntry(AuditLogger audit, Element logEntryElement) { LogEntry logEntry = audit.newLogEntry(); logEntry.setCategory(logEntryElement.attributeValue("category")); logEntry.setComment(logEntryElement.attributeValue("comment")); logEntry.setDocLifeCycle(logEntryElement.attributeValue("docLifeCycle")); logEntry.setDocPath(logEntryElement.attributeValue("docPath")); logEntry.setDocType(logEntryElement.attributeValue("docType")); logEntry.setDocUUID(logEntryElement.attributeValue("docUUID")); logEntry.setRepositoryId(logEntryElement.attributeValue("repoId")); try { Date creationDate = getDateFormat().parse(logEntryElement.attributeValue("creationDate")); logEntry.setEventDate(creationDate); } catch (ParseException e) { log.error(e, e); } logEntry.setEventId(logEntryElement.attributeValue("eventId")); logEntry.setPrincipalName(logEntryElement.attributeValue("principalName")); return logEntry; } /** * Specifies date-string conversion. */ protected static DateFormat getDateFormat() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } protected static void writeXML(Document doc, OutputStream out) throws IOException { OutputFormat format = OutputFormat.createPrettyPrint(); XMLWriter writer = new XMLWriter(out, format); writer.write(doc); } private static Document loadXML(InputStream in) throws IOException { try { // the SAXReader is closing the stream so that we need to copy the // content somewhere ByteArrayOutputStream baos = new ByteArrayOutputStream(); IOUtils.copy(in, baos); return new SAXReader().read(new ByteArrayInputStream(baos.toByteArray())); } catch (DocumentException e) { IOException ioe = new IOException("Failed to read log entry " + ": " + e.getMessage()); ioe.setStackTrace(e.getStackTrace()); throw ioe; } } public static List<LogEntry> translate(List<LogEntry> docLogs, DocumentRef newRef) { List<LogEntry> newList = new ArrayList<LogEntry>(); for (LogEntry logEntry : docLogs) { LogEntry newLogEntry = translate(logEntry, newRef); newList.add(newLogEntry); } return newList; } /** * Should be overridden if log data structure is changed. */ private static LogEntry translate(LogEntry logEntry, DocumentRef newRef) { LogEntry newLogEntry; try { newLogEntry = (LogEntry) BeanUtils.cloneBean(logEntry); } catch (ReflectiveOperationException e) { throw new NuxeoException("cannot clone bean " + logEntry, e); } newLogEntry.setDocUUID(newRef); return newLogEntry; } }