001/* 002 * (C) Copyright 2006-2007 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 * 018 * $Id$ 019 */ 020 021package org.nuxeo.ecm.platform.audit.io; 022 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.OutputStream; 026import java.io.Serializable; 027import java.util.ArrayList; 028import java.util.Collection; 029import java.util.Collections; 030import java.util.HashMap; 031import java.util.List; 032import java.util.Map; 033 034import org.apache.commons.logging.Log; 035import org.apache.commons.logging.LogFactory; 036import org.nuxeo.ecm.core.api.CloseableCoreSession; 037import org.nuxeo.ecm.core.api.CoreInstance; 038import org.nuxeo.ecm.core.api.CoreSession; 039import org.nuxeo.ecm.core.api.DocumentModel; 040import org.nuxeo.ecm.core.api.DocumentNotFoundException; 041import org.nuxeo.ecm.core.api.DocumentRef; 042import org.nuxeo.ecm.core.api.IdRef; 043import org.nuxeo.ecm.core.api.NuxeoException; 044import org.nuxeo.ecm.core.io.DocumentTranslationMap; 045import org.nuxeo.ecm.platform.audit.api.LogEntry; 046import org.nuxeo.ecm.platform.audit.api.Logs; 047import org.nuxeo.ecm.platform.io.api.AbstractIOResourceAdapter; 048import org.nuxeo.ecm.platform.io.api.IOResources; 049import org.nuxeo.runtime.api.Framework; 050 051/** 052 * Adapter for import/export of audit logs. 053 * 054 * @author <a href="mailto:[email protected]">Dragos Mihalache</a> 055 */ 056public class IOAuditAdapter extends AbstractIOResourceAdapter { 057 058 private static final Log log = LogFactory.getLog(IOAuditAdapter.class); 059 060 private static final long serialVersionUID = -3661302796286246086L; 061 062 /** 063 * Should be overridden if IOLogEntryBase is subclassed. 064 * 065 * @return IOLogEntryBase instance that will know how to write and read log entries 066 */ 067 protected IOLogEntryBase getLogEntryHelper() { 068 return new IOLogEntryBase(); 069 } 070 071 @Override 072 public void setProperties(Map<String, Serializable> properties) { 073 } 074 075 /** 076 * Extract logs involving given documents. 077 * <p> 078 * The adapter properties will filter which logs must be taken into account. 079 */ 080 @Override 081 public IOResources extractResources(String repo, Collection<DocumentRef> sources) { 082 if (sources == null || sources.isEmpty()) { 083 return null; 084 } 085 try (CloseableCoreSession session = CoreInstance.openCoreSessionSystem(repo)) { 086 Map<DocumentRef, List<LogEntry>> docLogs = new HashMap<DocumentRef, List<LogEntry>>(); 087 088 Logs logService = Framework.getService(Logs.class); 089 090 for (DocumentRef docRef : sources) { 091 try { 092 final String uuid; 093 if (docRef.type() == DocumentRef.ID) { 094 uuid = docRef.toString(); 095 } else { 096 DocumentModel doc = session.getDocument(docRef); 097 uuid = doc.getId(); 098 } 099 100 List<LogEntry> logEntries = logService.getLogEntriesFor(uuid, repo); 101 102 docLogs.put(docRef, logEntries); 103 } catch (DocumentNotFoundException e) { 104 List<LogEntry> emptyList = Collections.emptyList(); 105 docLogs.put(docRef, emptyList); 106 continue; 107 } 108 } 109 return new IOAuditResources(docLogs); 110 } 111 } 112 113 @Override 114 public void getResourcesAsXML(OutputStream out, IOResources resources) { 115 if (!(resources instanceof IOAuditResources)) { 116 return; 117 } 118 IOAuditResources auditResources = (IOAuditResources) resources; 119 120 List<LogEntry> logEntries = new ArrayList<LogEntry>(); 121 122 Map<DocumentRef, List<LogEntry>> docLogs = auditResources.getLogsMap(); 123 124 Collection<List<LogEntry>> all = docLogs.values(); 125 for (List<LogEntry> list : all) { 126 logEntries.addAll(list); 127 } 128 129 try { 130 IOLogEntryBase.write(logEntries, out); 131 } catch (IOException e) { 132 throw new NuxeoException("Cannot write logs", e); 133 } 134 } 135 136 @Override 137 public IOResources loadResourcesFromXML(InputStream stream) { 138 List<LogEntry> allEntries; 139 try { 140 allEntries = IOLogEntryBase.read(stream); 141 } catch (IOException e) { 142 throw new NuxeoException("Cannot read entries from " + stream); 143 } 144 145 // will put each log entry to its correspondent document ref 146 Map<DocumentRef, List<LogEntry>> docLogs = new HashMap<DocumentRef, List<LogEntry>>(); 147 for (LogEntry logEntry : allEntries) { 148 DocumentRef docRef = new IdRef(logEntry.getDocUUID()); 149 150 List<LogEntry> logEntries = docLogs.get(docRef); 151 if (logEntries == null) { 152 logEntries = new ArrayList<LogEntry>(); 153 docLogs.put(docRef, logEntries); 154 } 155 logEntries.add(logEntry); 156 } 157 158 return new IOAuditResources(docLogs); 159 } 160 161 @Override 162 public void storeResources(IOResources newResources) { 163 if (!(newResources instanceof IOAuditResources)) { 164 return; 165 } 166 Logs logService = Framework.getService(Logs.class); 167 IOAuditResources auditResources = (IOAuditResources) newResources; 168 Map<DocumentRef, List<LogEntry>> docLogs = auditResources.getLogsMap(); 169 for (Map.Entry<DocumentRef, List<LogEntry>> mapEntry : docLogs.entrySet()) { 170 DocumentRef docRef = mapEntry.getKey(); 171 List<LogEntry> logs = mapEntry.getValue(); 172 // need to set the given docRef - so transfer with the help of 173 // IOLogEntryBase (subclass eventually) 174 List<LogEntry> newLogs = IOLogEntryBase.translate(logs, docRef); 175 logService.addLogEntries(newLogs); 176 } 177 } 178 179 @Override 180 public IOResources translateResources(String repo, IOResources resources, DocumentTranslationMap map) { 181 if (map == null) { 182 return null; 183 } 184 if (!(resources instanceof IOAuditResources)) { 185 return resources; 186 } 187 188 IOAuditResources auditResources = (IOAuditResources) resources; 189 Map<DocumentRef, List<LogEntry>> newResourcesMap = new HashMap<DocumentRef, List<LogEntry>>(); 190 191 for (Map.Entry<DocumentRef, List<LogEntry>> entry : auditResources.getLogsMap().entrySet()) { 192 DocumentRef oldRef = entry.getKey(); 193 DocumentRef newRef = map.getDocRefMap().get(oldRef); 194 if (newRef == null) { 195 if (log.isErrorEnabled()) { 196 log.error("newRef does not exist in translation map for " + oldRef); 197 } 198 continue; 199 } 200 List<LogEntry> docLogs = auditResources.getDocumentLogs(oldRef); 201 202 // need to set the given docRef - so transfer with the help of 203 // IOLogEntryBase (subclass eventually) 204 List<LogEntry> newLogs = IOLogEntryBase.translate(docLogs, newRef); 205 newResourcesMap.put(newRef, newLogs); 206 } 207 208 return new IOAuditResources(newResourcesMap); 209 } 210 211}