001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Thomas Roger 016 */ 017 018package org.nuxeo.ecm.core.security; 019 020import static org.nuxeo.ecm.core.api.event.CoreEventConstants.DOCUMENT_REFS; 021import static org.nuxeo.ecm.core.api.event.CoreEventConstants.REPOSITORY_NAME; 022import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.ACE_STATUS_UPDATED; 023 024import java.io.Serializable; 025import java.text.SimpleDateFormat; 026import java.util.ArrayList; 027import java.util.Date; 028import java.util.List; 029import java.util.Map; 030 031import org.nuxeo.ecm.core.api.DocumentRef; 032import org.nuxeo.ecm.core.api.IdRef; 033import org.nuxeo.ecm.core.api.IterableQueryResult; 034import org.nuxeo.ecm.core.api.security.ACP; 035import org.nuxeo.ecm.core.event.EventContext; 036import org.nuxeo.ecm.core.event.EventService; 037import org.nuxeo.ecm.core.event.impl.EventContextImpl; 038import org.nuxeo.ecm.core.query.sql.NXQL; 039import org.nuxeo.ecm.core.work.AbstractWork; 040import org.nuxeo.runtime.api.Framework; 041import org.nuxeo.runtime.transaction.TransactionRuntimeException; 042 043/** 044 * Work updating ACE status. 045 * 046 * @since 7.4 047 */ 048public class UpdateACEStatusWork extends AbstractWork { 049 050 public static final int DEFAULT_BATCH_SIZE = 20; 051 052 public static final String ID = "updateACEStatus"; 053 054 public static final String CATEGORY = "updateACEStatus"; 055 056 public static final String QUERY = "SELECT ecm:uuid FROM Document WHERE (ecm:acl/*1/status = 0 AND ecm:acl/*1/begin <= TIMESTAMP '%s') OR (ecm:acl/*1/status = 1 AND ecm:acl/*1/end <= TIMESTAMP '%s')"; 057 058 public static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 059 060 protected int batchSize = DEFAULT_BATCH_SIZE; 061 062 public UpdateACEStatusWork() { 063 super(ID); 064 } 065 066 @Override 067 public void work() { 068 setStatus("Updating ACE status"); 069 initSession(); 070 071 Date now = new Date(); 072 String formattedDate = FORMATTER.format(now); 073 074 IterableQueryResult result = session.queryAndFetch(String.format(QUERY, formattedDate, formattedDate), 075 NXQL.NXQL); 076 List<String> docIds = new ArrayList<>(); 077 try { 078 for (Map<String, Serializable> map : result) { 079 docIds.add((String) map.get("ecm:uuid")); 080 } 081 } finally { 082 result.close(); 083 } 084 085 int acpUpdatedCount = 0; 086 List<DocumentRef> processedDocIds = new ArrayList<>(); 087 for (String docId : docIds) { 088 try { 089 DocumentRef ref = new IdRef(docId); 090 ACP acp = session.getACP(ref); 091 session.setACP(ref, acp, true); 092 acpUpdatedCount++; 093 processedDocIds.add(ref); 094 if (acpUpdatedCount % batchSize == 0) { 095 fireACEStatusUpdatedEvent(processedDocIds); 096 commitOrRollbackTransaction(); 097 startTransaction(); 098 processedDocIds.clear(); 099 } 100 } catch (TransactionRuntimeException e) { 101 if (e.getMessage().contains("Transaction timeout")) { 102 batchSize = 1; 103 } 104 throw e; 105 } 106 } 107 fireACEStatusUpdatedEvent(processedDocIds); 108 109 setStatus(null); 110 } 111 112 protected void fireACEStatusUpdatedEvent(List<DocumentRef> docRefs) { 113 EventContext eventContext = new EventContextImpl(session, session.getPrincipal()); 114 eventContext.setProperty(DOCUMENT_REFS, (Serializable) docRefs); 115 eventContext.setProperty(REPOSITORY_NAME, session.getRepositoryName()); 116 Framework.getService(EventService.class).fireEvent(ACE_STATUS_UPDATED, eventContext); 117 } 118 119 @Override 120 public String getCategory() { 121 return CATEGORY; 122 } 123 124 @Override 125 public String getTitle() { 126 return "Updating ACE status"; 127 } 128 129 @Override 130 public int getRetryCount() { 131 return 10; 132 } 133}