mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-30 18:15:39 +00:00
41597: ALF-1907: Check out rule is active for spaces - Merged in fix from DEV - Changed List of applicable types to a Set - Added quick initial checks against the set before doing the subtype checks - Various typo fixes 41598: Add an additional line of INFO to log the database details 41599: Fix for ALF-8374 - Simple view: incorrect file type icon for *.page and *.eps files 41600: Merge DEV to V4.1-BUG-FIX 41478 : ALF-14078: CLONE - Saving files with apps on Mac OS X Lion in CIFS doesn't invoke rules 41605: Fix for ALF-14653 - Share - Page link created wrongly in wiki. Solution to split wiki page name and title from Alex Bykov. 41608: CIFS cluster saving of text file fails. ALF-14179 The client releases the oplock by closing the file, if a remote oplock break was used then a notification to the remote node was missing in this case. 41616: ALF-13577:modified the delete site REST API to set the status code to 409 if a node is locked. 41624: MT: ALF-14331 - UserUsageTrackingComponent fails if disabled (in MT config) - defensive fix (exact steps do not repeat) - may also fix ALF-15956 41652: more debug 41653: Fix for ALF-15965 - IE9 - Script error occurs when manage aspect for a document 41655: Merged BRANCHES/V4.1 to BRANCHES/DEV/V4.1-BUG-FIX (RECORD ONLY) 41654: Fix for ALF-15965 - hand merged back from rev 41653 41658: ALF-14967: Task operations through task-forms now audited 41664: Reverse-merging change 41616 out of the product due to file formatting irregularities. This checkin was a fix for ALF-13577. A subsequent check-in will add the same fix but without the formatting problems. 41665: ALF-11452: Disabling JBPM now prevents jobexecutor thread from starting and consuming unneeded resources 41671: Reimplementation of fix for ALF-13577. Slight edit on previous fix. It now lets the NodeLockedException out of the Java layer and 'catches' this exception in the JavaScript layer. The API returns a 409 (conflict) if a NodeLockedException makes it to the JavaScript - the previous fix was returning 409 for *any* AlfrescoRuntimeException thrown during a site delete. Also this checkin preserves the whitespace/file layout of the preceding version. 41688: ALF-15867 WikiServiceImplTest failing on SQL Server - Switched WikiService_transaction bean over to using RetryingTransactionInterceptor 41720: ALF-15967: Using START_USER_ID_ instead of "initiator" property to query process instances started by user X to prevent extra joins 41730: Fix for ALF-15995 NodeRef is missing in log on "Problem converting to Freemarker" error 41743: ALF-9779 REGRESSION: FTP - Failed to retrieve directory listing for tenant user 41745: Removed a HomeShareMapper - there were two 41747: Fix for ALF-15811 SOLR query increases DocBitSet inefficiently Part of ALF-14861 SOLR to scale for non-admin users in 100k sites and a subgroup of each of 1000 independent groupings with 1000 subgroups 41748: Fix for ALF-15950 Solr: throws NPE: org.alfresco.solr.SolrLuceneAnalyser.loadAnalyzer - return default analyzer 41752: Fix for ALF-13634 Re-created category won't show up again on a node in Document Library. 41779: ALF-11283 - Got the home share mapper up and working after some refactoring. 41795: Fix for ALF-14361 CMIS object type definition for Document and Folder not spec compliant 41796: ALF-16008: missing column on clean Alfresco and after upgrade from 3.4.10 (703) - Schema-Reference for DB2 referenced a non-existent column. 41802: Fixed ALF-16029: TransactionCleanupTest throws constraint violations - Fallout from ALF-12358; sys:deleted node types have a mandatory property - Before bulk-deleting nodes, we need to delete properties - Use overriding DAo for MySQL. Other DBs can use standard delete with joins - NB: Fixed TransactionalCleanupTest to double-check the purge job 41822: Refactor to both Share Mappers. 41838: BDE-85: Deploy alfresco-mmt with a proper pom.xml containing dependencies Also, refactor Maven deployment to use a macro 41858: ALF-14444 - CloudSync: Ensure unknown properties when synced to Cloud are ignored properly 41876: Fix ALF-16067 - Items with cm:versionable aspect [custom aspect added] throw errors in Share UI 41877: Updated Spring Surf libs (1148) - downgrades module deployment error messages 41878: ALF-16069 - RU: 'Web Deployed' folder is not localized if Alfresco is installed with Russian locale. 41879: Fix non-continuous build, trying to call continuous-init from maven-env-prerequisites 41918: Merged PATCHES/V4.1.1 to V4.1-BUG-FIX 41657: ALF-15965 - IE9 - Script error occurs when manage aspect for a document (correct 4.1.1 branch this time) 41834: Merged DEV to V4.1.1 (4.1.1) 41827: ALF-15983: SPP: Meeting space: all-day event is displayed on the day before specified during creation Removing of time zone has been modified to be sensitive to Outlook meeting events which are not requiring special conversion for the start and end dates 41835: Merged DEV to V4.1.1 (4.1.1) 41833: ALF-16038 : DB2: Upgrade script needed to remove ALFUSER.ACT_HI_ACTINST.OWNER_ The patch was created to remove an unnecessary column in DB2. 41845: Reverse merge: << In attempt to clear 12 new DB2 build errors - don't think it is going to work >> 41835: Merged DEV to V4.1.1 (4.1.1) 41833: ALF-16038 : DB2: Upgrade script needed to remove ALFUSER.ACT_HI_ACTINST.OWNER_ The patch was created to remove an unnecessary column in DB2. Merged V4.1-BUG-FIX (4.1.2) to V4.1.1 (4.1.1) 41337: Merged V3.4-BUG-FIX (3.4.11) to V4.1-BUG-FIX (4.1.2) 41336: TransformerDebug: Use debug rather than trace when there are transformers but they are all unavailable. 41868: Reverse the reverse merge (back to r41835 state used in build #33 given to QA) 41845: Reverse merge: << In attempt to clear 12 new DB2 build errors - don't think it is going to work >> 41835: Merged DEV to V4.1.1 (4.1.1) 41833: ALF-16038 : DB2: Upgrade script needed to remove ALFUSER.ACT_HI_ACTINST.OWNER_ The patch was created to remove an unnecessary column in DB2. Merged V4.1-BUG-FIX (4.1.2) to V4.1.1 (4.1.1) 41337: Merged V3.4-BUG-FIX (3.4.11) to V4.1-BUG-FIX (4.1.2) 41336: TransformerDebug: Use debug rather than trace when there are transformers but they are all unavailable. 41914: Merged DEV to PATCHES/V4.1.1 41909: ALF-16078 : DB2: it's impossible to upgrade Alfresco from 3.4.10 to 4.1.1 (build 33). The remove-column-activiti.sql was marked as optional. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@41919 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
483 lines
13 KiB
Java
483 lines
13 KiB
Java
/*
|
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
|
*
|
|
* This file is part of Alfresco
|
|
*
|
|
* Alfresco 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package org.alfresco.filesys.alfresco;
|
|
|
|
import java.util.Enumeration;
|
|
import java.util.Hashtable;
|
|
|
|
import org.springframework.extensions.config.ConfigElement;
|
|
import org.alfresco.error.AlfrescoRuntimeException;
|
|
import org.alfresco.filesys.AlfrescoConfigSection;
|
|
import org.alfresco.filesys.repo.ContentContext;
|
|
import org.alfresco.jlan.debug.Debug;
|
|
import org.alfresco.jlan.server.SrvSession;
|
|
import org.alfresco.jlan.server.auth.InvalidUserException;
|
|
import org.alfresco.jlan.server.config.ConfigId;
|
|
import org.alfresco.jlan.server.config.ConfigurationListener;
|
|
import org.alfresco.jlan.server.config.InvalidConfigurationException;
|
|
import org.alfresco.jlan.server.config.ServerConfiguration;
|
|
import org.alfresco.jlan.server.core.ShareMapper;
|
|
import org.alfresco.jlan.server.core.ShareType;
|
|
import org.alfresco.jlan.server.core.SharedDevice;
|
|
import org.alfresco.jlan.server.core.SharedDeviceList;
|
|
import org.alfresco.jlan.server.filesys.DiskInterface;
|
|
import org.alfresco.jlan.server.filesys.DiskSharedDevice;
|
|
import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
|
|
import org.alfresco.jlan.server.filesys.SrvDiskInfo;
|
|
import org.alfresco.jlan.server.filesys.quota.QuotaManager;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.StoreRef;
|
|
import org.alfresco.util.PropertyCheck;
|
|
import org.springframework.beans.factory.InitializingBean;
|
|
import org.alfresco.filesys.config.ServerConfigurationBean;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
/**
|
|
* Multi Tenant Share Mapper Class
|
|
*
|
|
* @author gkspencer
|
|
*/
|
|
public class MultiTenantShareMapper implements ShareMapper, ConfigurationListener, InitializingBean {
|
|
|
|
// Server configuration and configuration sections
|
|
private static final Log logger = LogFactory.getLog(MultiTenantShareMapper.class);
|
|
|
|
private ServerConfiguration m_config;
|
|
|
|
private FilesystemsConfigSection m_filesysConfig;
|
|
private AlfrescoConfigSection m_alfrescoConfig;
|
|
|
|
// Share name for multi-tenant connections
|
|
|
|
private String m_tenantShareName;
|
|
|
|
// Store name and root path
|
|
|
|
private String m_rootPath;
|
|
private String m_storeName;
|
|
|
|
// Table of tenant share lists indexed by tenant domain
|
|
|
|
private Hashtable<String, SharedDeviceList> m_tenantShareLists;
|
|
|
|
// Quota manager to use when creating multi-tenant shares
|
|
|
|
private QuotaManager m_quotaManager;
|
|
|
|
private DiskInterface repoDiskInterface;
|
|
|
|
/**
|
|
* Default constructor
|
|
*/
|
|
public MultiTenantShareMapper()
|
|
{
|
|
}
|
|
|
|
public void init()
|
|
{
|
|
PropertyCheck.mandatory(this, "ServerConfiguration", m_config);
|
|
PropertyCheck.mandatory(this, "Tenant share name", m_tenantShareName);
|
|
PropertyCheck.mandatory(this, "repoDiskInterface", getRepoDiskInterface());
|
|
PropertyCheck.mandatory(this, "Store name", m_storeName);
|
|
PropertyCheck.mandatory(this, "Root Path", m_rootPath);
|
|
}
|
|
|
|
/**
|
|
* Initialize the share mapper
|
|
*
|
|
* @param config ServerConfiguration
|
|
* @param params ConfigElement
|
|
* @exception InvalidConfigurationException
|
|
*/
|
|
public void initializeMapper(ServerConfiguration config, ConfigElement params)
|
|
throws InvalidConfigurationException
|
|
{
|
|
if(logger.isDebugEnabled())
|
|
{
|
|
logger.debug("initialiseMapper");
|
|
}
|
|
|
|
// Save the server configuration
|
|
|
|
setServerConfiguration(config);
|
|
|
|
// Complete initialization
|
|
afterPropertiesSet();
|
|
}
|
|
|
|
public void afterPropertiesSet()
|
|
{
|
|
// Filesystem configuration will usually be initialized after the security configuration so we need to plug in
|
|
// a listener to initialize it later
|
|
|
|
m_filesysConfig = (FilesystemsConfigSection) m_config.getConfigSection( FilesystemsConfigSection.SectionName);
|
|
|
|
// Get the Alfresco configuration section
|
|
|
|
m_alfrescoConfig = (AlfrescoConfigSection) m_config.getConfigSection( AlfrescoConfigSection.SectionName);
|
|
|
|
if ( m_filesysConfig == null || m_alfrescoConfig == null)
|
|
m_config.addListener( this);
|
|
|
|
// Create the tenant share lists table
|
|
|
|
m_tenantShareLists = new Hashtable<String, SharedDeviceList>();
|
|
}
|
|
|
|
/**
|
|
* Find a share using the name and type for the specified client.
|
|
*
|
|
* @param host String
|
|
* @param name String
|
|
* @param typ int
|
|
* @param sess SrvSession
|
|
* @param create boolean
|
|
* @return SharedDevice or null if no matching device was found
|
|
* @exception InvalidUserException
|
|
*/
|
|
public SharedDevice findShare(String host, String name, int typ, SrvSession sess, boolean create)
|
|
throws InvalidUserException {
|
|
|
|
// Check if this is a tenant user
|
|
|
|
if ( m_alfrescoConfig.getTenantService().isEnabled() &&
|
|
m_alfrescoConfig.getTenantService().isTenantUser() &&
|
|
typ != ShareType.ADMINPIPE)
|
|
{
|
|
return findTenantShare(host, name, typ, sess, create);
|
|
}
|
|
|
|
// Find the required share by name/type. Use a case sensitive search first, if that fails use a case
|
|
// insensitive search.
|
|
|
|
SharedDevice share = m_filesysConfig.getShares().findShare(name, typ, false);
|
|
|
|
if ( share == null) {
|
|
|
|
// Try a case insensitive search for the required share
|
|
|
|
share = m_filesysConfig.getShares().findShare(name, typ, true);
|
|
}
|
|
|
|
// Check if the share is available
|
|
|
|
if ( share != null && share.getContext() != null && share.getContext().isAvailable() == false)
|
|
share = null;
|
|
|
|
// Return the shared device, or null if no matching device was found
|
|
|
|
return share;
|
|
}
|
|
|
|
/**
|
|
* Delete temporary shares for the specified session
|
|
*
|
|
* @param sess SrvSession
|
|
*/
|
|
public void deleteShares(SrvSession sess) {
|
|
|
|
// Check if the session has any dynamic shares
|
|
|
|
if ( sess.hasDynamicShares() == false)
|
|
return;
|
|
|
|
// Delete the dynamic shares
|
|
|
|
SharedDeviceList shares = sess.getDynamicShareList();
|
|
Enumeration<SharedDevice> enm = shares.enumerateShares();
|
|
|
|
while ( enm.hasMoreElements()) {
|
|
|
|
// Get the current share from the list
|
|
|
|
SharedDevice shr = enm.nextElement();
|
|
|
|
// Close the shared device
|
|
|
|
shr.getContext().CloseContext();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the list of available shares.
|
|
*
|
|
* @param host String
|
|
* @param sess SrvSession
|
|
* @param allShares boolean
|
|
* @return SharedDeviceList
|
|
*/
|
|
public SharedDeviceList getShareList(String host, SrvSession sess, boolean allShares) {
|
|
|
|
// Check that the filesystems configuration is valid
|
|
|
|
if ( m_filesysConfig == null)
|
|
return null;
|
|
|
|
// Check if this is a tenant user
|
|
|
|
if ( m_alfrescoConfig.getTenantService().isEnabled() && m_alfrescoConfig.getTenantService().isTenantUser())
|
|
{
|
|
return getTenantShareList(host, sess, allShares);
|
|
}
|
|
|
|
// Make a copy of the global share list and add the per session dynamic shares
|
|
|
|
SharedDeviceList shrList = new SharedDeviceList( m_filesysConfig.getShares());
|
|
|
|
if ( sess != null && sess.hasDynamicShares())
|
|
{
|
|
// Add the per session dynamic shares
|
|
shrList.addShares(sess.getDynamicShareList());
|
|
}
|
|
|
|
// Remove unavailable shares from the list and return the list
|
|
|
|
if ( allShares == false)
|
|
{
|
|
shrList.removeUnavailableShares();
|
|
}
|
|
return shrList;
|
|
}
|
|
|
|
/**
|
|
* Close the share mapper, release any resources.
|
|
*/
|
|
public void closeMapper() {
|
|
|
|
// Close all the tenant shares
|
|
|
|
// TODO:
|
|
}
|
|
|
|
/**
|
|
* Configuration changed
|
|
*
|
|
* @param id int
|
|
* @param config Serverconfiguration
|
|
* @param newVal Object
|
|
* @return int
|
|
* @throws InvalidConfigurationException
|
|
*/
|
|
public int configurationChanged(int id, ServerConfiguration config, Object newVal)
|
|
throws InvalidConfigurationException {
|
|
|
|
// Check if the filesystems configuration section has been added
|
|
|
|
if ( id == ConfigId.ConfigSection) {
|
|
|
|
// Check if the section added is the filesystems config
|
|
|
|
if (newVal instanceof FilesystemsConfigSection)
|
|
m_filesysConfig = (FilesystemsConfigSection) newVal;
|
|
|
|
// Or the Alfresco config
|
|
|
|
else if (newVal instanceof AlfrescoConfigSection)
|
|
m_alfrescoConfig = (AlfrescoConfigSection) newVal;
|
|
|
|
// Return a dummy status
|
|
|
|
return ConfigurationListener.StsAccepted;
|
|
}
|
|
|
|
|
|
// Return a dummy status
|
|
|
|
return ConfigurationListener.StsIgnored;
|
|
}
|
|
|
|
/**
|
|
* Find a share for a tenant
|
|
*
|
|
* @param host String
|
|
* @param name String
|
|
* @param typ int
|
|
* @param sess SrvSession
|
|
* @param create boolean
|
|
* @return SharedDevice
|
|
* @exception InvalidUserException
|
|
*/
|
|
private final SharedDevice findTenantShare(String host, String name, int typ, SrvSession sess, boolean create)
|
|
throws InvalidUserException {
|
|
|
|
// Get the share list for the tenant
|
|
|
|
SharedDeviceList shareList = getTenantShareList(host, sess, true);
|
|
if ( shareList == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// Search for the required share in the list of shares for the tennant
|
|
|
|
return shareList.findShare( name, typ, true);
|
|
}
|
|
|
|
/**
|
|
* Return the list of available shares for a particular tenant
|
|
*
|
|
* @param host String
|
|
* @param sess SrvSession
|
|
* @param allShares boolean
|
|
* @return SharedDeviceList
|
|
*/
|
|
private final SharedDeviceList getTenantShareList(String host, SrvSession sess, boolean allShares) {
|
|
|
|
// Get the tenant user domain
|
|
|
|
String tenantDomain = m_alfrescoConfig.getTenantService().getCurrentUserDomain();
|
|
|
|
// Get the share list for the current domain
|
|
|
|
SharedDeviceList shareList = null;
|
|
|
|
if(m_tenantShareLists.containsKey(tenantDomain))
|
|
{
|
|
shareList = m_tenantShareLists.get( tenantDomain);
|
|
}
|
|
|
|
synchronized ( m_tenantShareLists)
|
|
{
|
|
// Get the tenant specific share list
|
|
|
|
shareList = m_tenantShareLists.get( tenantDomain);
|
|
|
|
if ( shareList == null)
|
|
{
|
|
// Create the tenant specific share list
|
|
|
|
shareList = new SharedDeviceList();
|
|
|
|
// Create a tenant specific share for this domain
|
|
|
|
shareList.addShare( createTenantShare(tenantDomain));
|
|
|
|
// Store the list for use by other members of this domain
|
|
|
|
m_tenantShareLists.put( tenantDomain, shareList);
|
|
}
|
|
}
|
|
|
|
// Return the tenant specific share list
|
|
|
|
return shareList;
|
|
}
|
|
|
|
/**
|
|
* Create a tenant domain specific share
|
|
*/
|
|
private final DiskSharedDevice createTenantShare(String tenantDomain)
|
|
{
|
|
logger.debug("create tenant share for domain " + tenantDomain);
|
|
StoreRef storeRef = new StoreRef(getStoreName());
|
|
NodeRef rootNodeRef = new NodeRef(storeRef.getProtocol(), storeRef.getIdentifier(), "dummy");
|
|
|
|
// Root nodeRef is required for storeRef part
|
|
|
|
rootNodeRef = m_alfrescoConfig.getTenantService().getRootNode(
|
|
m_alfrescoConfig.getNodeService(),
|
|
m_alfrescoConfig.getSearchService(),
|
|
m_alfrescoConfig.getNamespaceService(),
|
|
getRootPath(),
|
|
rootNodeRef);
|
|
|
|
// Create the disk driver and context
|
|
|
|
DiskInterface diskDrv = getRepoDiskInterface();
|
|
ContentContext diskCtx = new ContentContext(m_tenantShareName, getStoreName(), getRootPath(), rootNodeRef);
|
|
|
|
// Set a quota manager for the share, if enabled
|
|
|
|
if ( m_quotaManager != null)
|
|
{
|
|
diskCtx.setQuotaManager( m_quotaManager);
|
|
}
|
|
|
|
if(m_config instanceof ServerConfigurationBean)
|
|
{
|
|
ServerConfigurationBean config = (ServerConfigurationBean)m_config;
|
|
|
|
config.initialiseRuntimeContext("cifs.tenant." + tenantDomain, diskCtx);
|
|
}
|
|
else
|
|
{
|
|
throw new AlfrescoRuntimeException("configuration error, unknown configuration bean");
|
|
}
|
|
|
|
// Default the filesystem to look like an 80Gb sized disk with 90% free space
|
|
|
|
diskCtx.setDiskInformation(new SrvDiskInfo(2560, 64, 512, 2304));
|
|
|
|
// Create a temporary shared device for the user to access the tenant company home directory
|
|
|
|
return new DiskSharedDevice(m_tenantShareName, diskDrv, diskCtx);
|
|
}
|
|
|
|
public void setServerConfiguration(ServerConfiguration config)
|
|
{
|
|
this.m_config = config;
|
|
}
|
|
|
|
public void setTenantShareName(String shareName)
|
|
{
|
|
m_tenantShareName = shareName;
|
|
}
|
|
|
|
/**
|
|
* Set the quota manager to be used by multi-tenant shares
|
|
*
|
|
* @param quotaManager QuotaManager
|
|
*/
|
|
public void setQuotaManager( QuotaManager quotaManager)
|
|
{
|
|
m_quotaManager = quotaManager;
|
|
}
|
|
|
|
public void setRootPath(String m_rootPath)
|
|
{
|
|
this.m_rootPath = m_rootPath;
|
|
}
|
|
|
|
public String getRootPath()
|
|
{
|
|
return m_rootPath;
|
|
}
|
|
|
|
public void setStoreName(String m_storeName)
|
|
{
|
|
this.m_storeName = m_storeName;
|
|
}
|
|
|
|
public String getStoreName()
|
|
{
|
|
return m_storeName;
|
|
}
|
|
|
|
public void setRepoDiskInterface(DiskInterface repoDiskInterface)
|
|
{
|
|
this.repoDiskInterface = repoDiskInterface;
|
|
}
|
|
|
|
public DiskInterface getRepoDiskInterface()
|
|
{
|
|
return repoDiskInterface;
|
|
}
|
|
}
|