/* * Copyright (C) 2012 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.services.jcr.impl.quota; import org.exoplatform.services.jcr.impl.backup.BackupException; import org.exoplatform.services.jcr.impl.dataflow.serialization.ZipObjectReader; import org.exoplatform.services.jcr.impl.dataflow.serialization.ZipObjectWriter; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import java.io.EOFException; import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.zip.ZipEntry; /** * @author <a href="abazko@exoplatform.com">Anatoliy Bazko</a> * @version $Id: AbstractQuotaPersister.java 34360 2009-07-22 23:58:59Z tolusha $ */ public abstract class AbstractQuotaPersister implements QuotaPersister { /** * Logger. */ protected final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.AbstractQuotaPersister"); /** * {@inheritDoc} */ public void setNodeDataSizeIfQuotaExists(String repositoryName, String workspaceName, String nodePath, long dataSize) { setNodeDataSize(repositoryName, workspaceName, nodePath, dataSize); try { getNodeQuotaOrGroupOfNodesQuota(repositoryName, workspaceName, nodePath); } catch (UnknownQuotaLimitException e) { removeNodeDataSize(repositoryName, workspaceName, nodePath); } } /** * {@inheritDoc} */ public void removeNodeQuotaAndDataSize(String repositoryName, String workspaceName, String nodePath) { removeNodeQuota(repositoryName, workspaceName, nodePath); if (getAcceptableGroupOfNodesQuota(repositoryName, workspaceName, nodePath) == null) { removeNodeDataSize(repositoryName, workspaceName, nodePath); } } /** * {@inheritDoc} */ public void removeGroupOfNodesAndDataSize(String repositoryName, String workspaceName, String patternPath) { removeGroupOfNodesQuota(repositoryName, workspaceName, patternPath); // removes data size for all nodes matched by pattern // only if only quota was not set explicitly for (String nodePath : getAllTrackedNodes(repositoryName, workspaceName)) { if (PathPatternUtils.acceptName(patternPath, nodePath)) { try { getNodeQuota(repositoryName, workspaceName, nodePath); } catch (UnknownQuotaLimitException e) { removeNodeDataSize(repositoryName, workspaceName, nodePath); } } } } /** * {@inheritDoc} */ public long getNodeQuotaOrGroupOfNodesQuota(String repositoryName, String workspaceName, String nodePath) throws UnknownQuotaLimitException { try { return getNodeQuota(repositoryName, workspaceName, nodePath); } catch (UnknownQuotaLimitException e) { String patternPath = getAcceptableGroupOfNodesQuota(repositoryName, workspaceName, nodePath); if (patternPath != null) { return getGroupOfNodesQuota(repositoryName, workspaceName, patternPath); } throw new UnknownQuotaLimitException("Quota for " + nodePath + " is not defined"); } } /** * {@inheritDoc} */ public boolean isNodeQuotaOrGroupOfNodesQuotaAsync(String repositoryName, String workspaceName, String nodePath) throws UnknownQuotaLimitException { try { return isNodeQuotaAsync(repositoryName, workspaceName, nodePath); } catch (UnknownQuotaLimitException e) { String patternPath = getAcceptableGroupOfNodesQuota(repositoryName, workspaceName, nodePath); if (patternPath != null) { return isGroupOfNodesQuotaAsync(repositoryName, workspaceName, patternPath); } throw new UnknownQuotaLimitException("Quota for " + nodePath + " is not defined"); } } /** * {@inheritDoc} */ public String getAcceptableGroupOfNodesQuota(String repositoryName, String workspaceName, String nodePath) { Set<String> patterns = getAllGroupOfNodesQuota(repositoryName, workspaceName); for (String patternPath : patterns) { if (PathPatternUtils.acceptName(patternPath, nodePath)) { return patternPath; } } return null; } /** * {@inheritDoc} */ public Set<String> getAllParentNodesWithQuota(String repositoryName, String workspaceName, String nodePath) { Set<String> quotableParents = new HashSet<String>(); for (String quoteablePath : getAllNodeQuota(repositoryName, workspaceName)) { if (nodePath.startsWith(quoteablePath)) { quotableParents.add(quoteablePath); } } for (String pattern : getAllGroupOfNodesQuota(repositoryName, workspaceName)) { if (PathPatternUtils.acceptDescendant(pattern, nodePath)) { String commonAncestor = PathPatternUtils.extractCommonAncestor(pattern, nodePath); quotableParents.add(commonAncestor); } } return quotableParents; } // ===============================================> backupable /** * {@inheritDoc} */ public void backupWorkspaceData(String repositoryName, String workspaceName, ZipObjectWriter out) throws BackupException { try { backupWorkspaceDataSize(repositoryName, workspaceName, out); backupWorkspaceQuota(repositoryName, workspaceName, out); backupAllNodeDataSize(repositoryName, workspaceName, out); backupAllNodeQuota(repositoryName, workspaceName, out); backupAllGroupOfNodesQuota(repositoryName, workspaceName, out); } catch (IOException e) { throw new BackupException(e.getMessage(), e); } } /** * {@inheritDoc} */ public void restoreWorkspaceData(String repositoryName, String workspaceName, ZipObjectReader in) throws BackupException { try { restoreWorkspaceDataSize(repositoryName, workspaceName, in); restoreWorkspaceQuota(repositoryName, workspaceName, in); restoreAllNodeDataSize(repositoryName, workspaceName, in); restoreAllNodeQuota(repositoryName, workspaceName, in); restoreAllGroupOfNodesQuota(repositoryName, workspaceName, in); } catch (IOException e) { throw new BackupException(e.getMessage(), e); } } private void backupWorkspaceQuota(String repositoryName, String workspaceName, ZipObjectWriter out) throws IOException { out.putNextEntry(new ZipEntry("workspace-quota-limit")); try { long quotaLimit = getWorkspaceQuota(repositoryName, workspaceName); out.writeLong(quotaLimit); } catch (UnknownQuotaLimitException e) { if (LOG.isTraceEnabled()) { LOG.trace(e.getMessage(), e); } } out.closeEntry(); } private void backupWorkspaceDataSize(String repositoryName, String workspaceName, ZipObjectWriter out) throws IOException { out.putNextEntry(new ZipEntry("workspace-data-size")); try { long size = getWorkspaceDataSize(repositoryName, workspaceName); out.writeLong(size); } catch (UnknownDataSizeException e) { if (LOG.isTraceEnabled()) { LOG.trace(e.getMessage(), e); } } out.closeEntry(); } private void backupAllNodeDataSize(String repositoryName, String workspaceName, ZipObjectWriter out) throws IOException { out.putNextEntry(new ZipEntry("workspace-nodes-data-size")); Set<String> paths = getAllTrackedNodes(repositoryName, workspaceName); out.writeInt(paths.size()); for (String nodePath : paths) { try { long size = getNodeDataSize(repositoryName, workspaceName, nodePath); out.writeString(nodePath); out.writeLong(size); } catch (UnknownDataSizeException e) { throw new IOException("Node is tracked but data size is unknown.", e); } } out.closeEntry(); } private void backupAllNodeQuota(String repositoryName, String workspaceName, ZipObjectWriter out) throws IOException { out.putNextEntry(new ZipEntry("workspace-all-node-quota")); Set<String> paths = getAllNodeQuota(repositoryName, workspaceName); out.writeInt(paths.size()); for (String nodePath : paths) { try { long quotaLimit = getNodeQuota(repositoryName, workspaceName, nodePath); boolean async = isNodeQuotaAsync(repositoryName, workspaceName, nodePath); out.writeString(nodePath); out.writeLong(quotaLimit); out.writeBoolean(async); } catch (UnknownQuotaLimitException e) { throw new IOException("Node is quoted but qouta limit is unknown.", e); } } out.closeEntry(); } private void backupAllGroupOfNodesQuota(String repositoryName, String workspaceName, ZipObjectWriter out) throws IOException { out.putNextEntry(new ZipEntry("workspace-all-group-of-nodes-quota")); Set<String> paths = getAllGroupOfNodesQuota(repositoryName, workspaceName); out.writeInt(paths.size()); for (String patternPath : paths) { try { long quotaLimit = getGroupOfNodesQuota(repositoryName, workspaceName, patternPath); boolean async = isGroupOfNodesQuotaAsync(repositoryName, workspaceName, patternPath); out.writeString(patternPath); out.writeLong(quotaLimit); out.writeBoolean(async); } catch (UnknownQuotaLimitException e) { throw new IOException("Node is quoted but qouta limit is unknown.", e); } } out.closeEntry(); } private void restoreWorkspaceQuota(String repositoryName, String workspaceName, ZipObjectReader in) throws IOException { in.getNextEntry(); try { Long quotaLimit = in.readLong(); setWorkspaceQuota(repositoryName, workspaceName, quotaLimit); } catch (EOFException e) { if (LOG.isTraceEnabled()) { LOG.trace(e.getMessage(), e); } } } private void restoreWorkspaceDataSize(String repositoryName, String workspaceName, ZipObjectReader in) throws IOException { in.getNextEntry(); try { Long dataSize = in.readLong(); setWorkspaceDataSize(repositoryName, workspaceName, dataSize); } catch (EOFException e) { if (LOG.isTraceEnabled()) { LOG.trace(e.getMessage(), e); } } } private void restoreAllNodeDataSize(String repositoryName, String workspaceName, ZipObjectReader in) throws IOException { in.getNextEntry(); int count = in.readInt(); for (int i = 0; i < count; i++) { String nodePath = in.readString(); long dataSize = in.readLong(); setNodeDataSize(repositoryName, workspaceName, nodePath, dataSize); } } private void restoreAllNodeQuota(String repositoryName, String workspaceName, ZipObjectReader in) throws IOException { in.getNextEntry(); int count = in.readInt(); for (int i = 0; i < count; i++) { String nodePath = in.readString(); long quotaLimit = in.readLong(); boolean asyncUpdate = in.readBoolean(); setNodeQuota(repositoryName, workspaceName, nodePath, quotaLimit, asyncUpdate); } } private void restoreAllGroupOfNodesQuota(String repositoryName, String workspaceName, ZipObjectReader in) throws IOException { in.getNextEntry(); int count = in.readInt(); for (int i = 0; i < count; i++) { String patternPath = in.readString(); long quotaLimit = in.readLong(); boolean asyncUpdate = in.readBoolean(); setGroupOfNodesQuota(repositoryName, workspaceName, patternPath, quotaLimit, asyncUpdate); } } }