/*
* 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.infinispan;
import org.exoplatform.commons.utils.SecurityHelper;
import org.exoplatform.container.configuration.ConfigurationManager;
import org.exoplatform.services.jcr.config.MappedParametrizedObjectEntry;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.impl.backup.BackupException;
import org.exoplatform.services.jcr.impl.quota.AbstractQuotaPersister;
import org.exoplatform.services.jcr.impl.quota.UnknownDataSizeException;
import org.exoplatform.services.jcr.impl.quota.UnknownQuotaLimitException;
import org.exoplatform.services.jcr.infinispan.CacheKey;
import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
import org.exoplatform.services.jcr.infinispan.PrivilegedISPNCacheHelper;
import org.infinispan.AdvancedCache;
import org.infinispan.context.Flag;
import java.io.Serializable;
import java.security.PrivilegedAction;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="abazko@exoplatform.com">Anatoliy Bazko</a>
* @version $Id: ISPNQuotaPersister.java 34360 2009-07-22 23:58:59Z tolusha $
*/
public class ISPNQuotaPersister extends AbstractQuotaPersister
{
/**
* ISPN cache.
*/
private AdvancedCache<Serializable, Object> cache;
/**
* ISPNQuotaPersister constructor.
*/
protected ISPNQuotaPersister(MappedParametrizedObjectEntry entry, ConfigurationManager cfm)
throws RepositoryConfigurationException
{
ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
cache = factory.createCache("quota", entry).getAdvancedCache();
cache.start();
}
/**
* {@inheritDoc}
*/
public void destroy()
{
PrivilegedISPNCacheHelper.stop(cache);
ISPNCacheFactory.releaseUniqueInstance(cache.getCacheManager());
}
/**
* {@inheritDoc}
*/
public void setNodeQuota(String repositoryName, String workspaceName, String nodePath, long quotaLimit,
boolean asyncUpdate)
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new NodeQuotaKey(workspaceUniqueName, nodePath);
QuotaValue value = new QuotaValue(quotaLimit, asyncUpdate);
cache.put(key, value);
}
/**
* {@inheritDoc}
*/
public void setGroupOfNodesQuota(String repositoryName, String workspaceName, String patternPath, long quotaLimit,
boolean asyncUpdate)
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new GroupOfNodesQuotaKey(workspaceUniqueName, patternPath);
QuotaValue value = new QuotaValue(quotaLimit, asyncUpdate);
cache.put(key, value);
}
/**
* {@inheritDoc}
*/
public long getNodeDataSize(String repositoryName, String workspaceName, String nodePath)
throws UnknownDataSizeException
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new NodeDataSizeKey(workspaceUniqueName, nodePath);
return getDataSize(key);
}
/**
* {@inheritDoc}
*/
public void setNodeDataSize(String repositoryName, String workspaceName, String nodePath, long dataSize)
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new NodeDataSizeKey(workspaceUniqueName, nodePath);
cache.put(key, dataSize);
}
/**
* {@inheritDoc}
*/
public void removeNodeDataSize(String repositoryName, String workspaceName, String nodePath)
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new NodeDataSizeKey(workspaceUniqueName, nodePath);
cache.remove(key);
}
/**
* {@inheritDoc}
*/
public long getWorkspaceQuota(String repositoryName, String workspaceName) throws UnknownQuotaLimitException
{
String wsUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new WorkspaceQuotaKey(wsUniqueName);
return getQuota(key);
}
/**
* {@inheritDoc}
*/
public void setWorkspaceQuota(final String repositoryName, final String workspaceName, final long quotaLimit)
{
SecurityHelper.doPrivilegedAction(new PrivilegedAction<Void>()
{
public Void run()
{
String wsUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new WorkspaceQuotaKey(wsUniqueName);
cache.put(key, quotaLimit);
return null;
}
});
}
/**
* {@inheritDoc}
*/
public void removeWorkspaceQuota(String repositoryName, String workspaceName)
{
String wsUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new WorkspaceQuotaKey(wsUniqueName);
cache.remove(key);
}
/**
* {@inheritDoc}
*/
public void setWorkspaceDataSize(final String repositoryName, final String workspaceName, final long dataSize)
{
SecurityHelper.doPrivilegedAction(new PrivilegedAction<Void>()
{
public Void run()
{
String wsUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new WorkspaceDataSizeKey(wsUniqueName);
cache.put(key, dataSize);
return null;
}
});
}
/**
* {@inheritDoc}
*/
public long getWorkspaceDataSize(String repositoryName, String workspaceName) throws UnknownDataSizeException
{
String wsUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new WorkspaceDataSizeKey(wsUniqueName);
return getDataSize(key);
}
/**
* {@inheritDoc}
*/
public long getRepositoryQuota(String repositoryName) throws UnknownQuotaLimitException
{
CacheKey key = new RepositoryQuotaKey(repositoryName);
return getQuota(key);
}
/**
* {@inheritDoc}
*/
public void setRepositoryQuota(final String repositoryName, final long quotaLimit)
{
SecurityHelper.doPrivilegedAction(new PrivilegedAction<Void>()
{
public Void run()
{
CacheKey key = new RepositoryQuotaKey(repositoryName);
cache.put(key, quotaLimit);
return null;
}
});
}
/**
* {@inheritDoc}
*/
public void removeRepositoryQuota(String repositoryName)
{
CacheKey key = new RepositoryQuotaKey(repositoryName);
cache.remove(key);
}
/**
* {@inheritDoc}
*/
public long getRepositoryDataSize(String repositoryName) throws UnknownDataSizeException
{
CacheKey key = new RepositoryDataSizeKey(repositoryName);
return getDataSize(key);
}
/**
* {@inheritDoc}
*/
public void setRepositoryDataSize(String repositoryName, long dataSize)
{
CacheKey key = new RepositoryDataSizeKey(repositoryName);
cache.put(key, dataSize);
}
/**
* {@inheritDoc}
*/
public long getGlobalDataSize() throws UnknownDataSizeException
{
CacheKey key = new GlobalDataSizeKey();
return getDataSize(key);
}
/**
* {@inheritDoc}
*/
public void setGlobalDataSize(final long dataSize)
{
SecurityHelper.doPrivilegedAction(new PrivilegedAction<Void>()
{
public Void run()
{
CacheKey key = new GlobalDataSizeKey();
cache.put(key, dataSize);
return null;
}
});
}
/**
* {@inheritDoc}
*/
public long getGlobalQuota() throws UnknownQuotaLimitException
{
CacheKey key = new GlobalQuotaKey();
return getQuota(key);
}
/**
* {@inheritDoc}
*/
public void setGlobalQuota(long quotaLimit)
{
CacheKey key = new GlobalQuotaKey();
cache.put(key, quotaLimit);
}
/**
* {@inheritDoc}
*/
public void removeGlobalQuota()
{
CacheKey key = new GlobalQuotaKey();
cache.remove(key);
}
/**
* {@inheritDoc}
*/
public void clearWorkspaceData(String repositoryName, String workspaceName) throws BackupException
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
for (Serializable cacheKey : cache.keySet())
{
if (cacheKey instanceof WorkspaceBasedKey)
{
if (workspaceUniqueName.equals(((WorkspaceBasedKey)cacheKey).getWorkspaceUniqueName()))
{
cache.remove(cacheKey);
}
}
}
}
/**
* {@inheritDoc}
*/
public long getNodeQuota(String repositoryName, String workspaceName, String nodePath)
throws UnknownQuotaLimitException
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new NodeQuotaKey(workspaceUniqueName, nodePath);
return getQuotaValue(key).getQuotaLimit();
}
/**
* {@inheritDoc}
*/
public long getGroupOfNodesQuota(String repositoryName, String workspaceName, String patternPath)
throws UnknownQuotaLimitException
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new GroupOfNodesQuotaKey(workspaceUniqueName, patternPath);
return getQuotaValue(key).getQuotaLimit();
}
/**
* {@inheritDoc}
*/
public boolean isNodeQuotaAsync(String repositoryName, String workspaceName, String nodePath)
throws UnknownQuotaLimitException
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new NodeQuotaKey(workspaceUniqueName, nodePath);
return getQuotaValue(key).getAsyncUpdate();
}
/**
* {@inheritDoc}
*/
public boolean isGroupOfNodesQuotaAsync(String repositoryName, String workspaceName, String patternPath)
throws UnknownQuotaLimitException
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new GroupOfNodesQuotaKey(workspaceUniqueName, patternPath);
return getQuotaValue(key).getAsyncUpdate();
}
/**
* {@inheritDoc}
*/
public Set<String> getAllNodeQuota(String repositoryName, String workspaceName)
{
Set<String> pathes = new HashSet<String>();
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
for (Serializable cacheKey : cache.keySet())
{
if (cacheKey instanceof NodeQuotaKey)
{
if (workspaceUniqueName.equals(((WorkspaceBasedKey)cacheKey).getWorkspaceUniqueName()))
{
pathes.add(((PathBasedKey)cacheKey).getPath());
}
}
}
return pathes;
}
/**
* {@inheritDoc}
*/
public Set<String> getAllGroupOfNodesQuota(String repositoryName, String workspaceName)
{
Set<String> pathes = new HashSet<String>();
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
for (Serializable cacheKey : cache.keySet())
{
if (cacheKey instanceof GroupOfNodesQuotaKey)
{
if (workspaceUniqueName.equals(((WorkspaceBasedKey)cacheKey).getWorkspaceUniqueName()))
{
pathes.add(((PathBasedKey)cacheKey).getPath());
}
}
}
return pathes;
}
/**
* {@inheritDoc}
*/
public Set<String> getAllTrackedNodes(String repositoryName, String workspaceName)
{
Set<String> pathes = new HashSet<String>();
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
for (Serializable cacheKey : cache.keySet())
{
if (cacheKey instanceof NodeDataSizeKey)
{
if (workspaceUniqueName.equals(((WorkspaceBasedKey)cacheKey).getWorkspaceUniqueName()))
{
pathes.add(((PathBasedKey)cacheKey).getPath());
}
}
}
return pathes;
}
/**
* {@inheritDoc}
*/
public void removeNodeQuota(String repositoryName, String workspaceName, String nodePath)
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new NodeQuotaKey(workspaceUniqueName, nodePath);
cache.remove(key);
}
/**
* {@inheritDoc}
*/
public void removeGroupOfNodesQuota(String repositoryName, String workspaceName, String patternPath)
{
String workspaceUniqueName = composeWorkspaceUniqueName(repositoryName, workspaceName);
CacheKey key = new GroupOfNodesQuotaKey(workspaceUniqueName, patternPath);
cache.remove(key);
}
// ==============================> private methods
/**
* Returns quota limit value otherwise throws {@link UnknownQuotaLimitException}.
*/
private long getQuota(CacheKey key) throws UnknownQuotaLimitException
{
Long size = (Long)cache.withFlags(Flag.FORCE_WRITE_LOCK).get(key);
if (size == null)
{
throw new UnknownQuotaLimitException("Quota was not set early");
}
return size;
}
/**
* Returns {@link QuotaValue} otherwise throws {@link UnknownQuotaLimitException}.
*/
private QuotaValue getQuotaValue(final CacheKey key) throws UnknownQuotaLimitException
{
QuotaValue quotaValue = SecurityHelper.doPrivilegedAction(new PrivilegedAction<QuotaValue>()
{
public QuotaValue run()
{
return (QuotaValue)cache.withFlags(Flag.FORCE_WRITE_LOCK).get(key);
}
});
if (quotaValue == null)
{
throw new UnknownQuotaLimitException("Quota was not set early");
}
return quotaValue;
}
/**
* Returns data size value otherwise throws {@link UnknownDataSizeException}.
*/
private long getDataSize(final CacheKey key) throws UnknownDataSizeException
{
Long size = SecurityHelper.doPrivilegedAction(new PrivilegedAction<Long>()
{
public Long run()
{
return (Long)cache.withFlags(Flag.FORCE_WRITE_LOCK).get(key);
}
});
if (size == null)
{
throw new UnknownDataSizeException("Data size is unknown");
}
return size;
}
/**
* Compose unique workspace name in global JCR instance.
*/
private String composeWorkspaceUniqueName(String repositoryName, String workspaceName)
{
StringBuilder builder = new StringBuilder();
builder.append(repositoryName);
builder.append('/');
builder.append(workspaceName);
builder.append('/');
return builder.toString();
}
}